I have created a SignalR hub and I want to unit test this hub. I have created multiple tests already, and when I fire them one by one they all succeed. But when I run them all at once a test is failing. The reason for failing is that this test is using a hub method that checks if some List has at least one value. The list should be empty in this test, but because other tests are running the list is filled by them.
How can I run this tests so each have their own instance of the hub?
As you can see below in the TryConnect() method it checks if the List ConnectedUsers is set and if there are more then MaxConnectedUsers in that list. In the test that is failing the list shouldn't be set and filled... but it is, because of other tests that are running.
How can I correctly test this?
For each test I create a mocked hub:
[TestMethod]
public void InitChat_Available()
{
HubWrapper hub = new HubWrapper();
hub.TryConnect();
Assert.AreEqual(1, hub.callerResponse.Count);
Assert.IsFalse((bool)hub.callerResponse[0]);
}
Init Method (Called in the HubWrapper constructor):
public void Init(string[] clientIds)
{
var connectionId = Guid.NewGuid().ToString();
var mockClients = new Mock<IHubCallerConnectionContext<dynamic>>();
var groupManagerMock = new Mock<IGroupManager>();
Clients = mockClients.Object;
caller.finishedInit = new Action<bool>((isAvailable) => callerResponse.Add(isAvailable));
mockClients.Setup(m => m.Caller).Returns((ExpandoObject)caller);
Groups = groupManagerMock.Object;
Dictionary<string, object> environment = new Dictionary<string, object>();
environment.Add("server.RemoteIpAddress", "127.0.0.10");
Context = new HubCallerContext(request: new ServerRequest(environment), connectionId: connectionId);
}
Hub TryConnect():
public void InitChat(string clientId)
{
bool isChatAvailable = (ConnectedUsers != null && ConnectedUsers.Count < MaxConnectedUsers);
Clients.Caller.finishedInit(isChatAvailable);
}
I've removed some (for this issue) unnecessary code.
Related
I am currently developing an app store style API which has the following entities (plus many others, but not relevant to the problem):
App (1 to many relationship to AppRevision - contains IEnumerable property)
AppRevision
Installation
I have come across an odd problem where the behaviour of EF differs in unit tests to when actually running the API, in that navigation properties are automatically being included when unit testing.
Take the following code snippet from my command handler:
App app = await this.context.Apps
.Include(a => a.Installations)
.FirstOrDefaultAsync(a => a.Id == command.AppId);
if (app != null) {
// Code omitted for brevity
}
When running the API, if I inspect app after this code has been run, the AppRevisions collection on the App entity is empty, as you would expect as I have not expliclity told EF to .Include(a => a.AppRevisions) - the API then throws an exception when trying to process code later on that needs this data to be there.
Now look at the following unit test for the same handler:
[Fact]
public async void Handle_ShouldAddInstallationRecord_WhenDataIsValid()
{
Guid testGuid = Guid.NewGuid();
CreateInstallationCommand command = new CreateInstallationCommand(testGuid, "ABC", "abc#abc.com", null);
using (TestContext context = new TestContextFactory().CreateTestContext())
{
context.Apps.Add(new App() { Id = testGuid });
context.AppRevisions.Add(new AppRevision() { Id = Guid.NewGuid(), AppId = testGuid, Status = AppRevisionStatus.Approved, IsListed = true });
await context.SaveChangesAsync();
CreateInstallationCommandHandler handler = new CreateInstallationCommandHandler(context);
CommandResult result = await handler.Handle(command, new CancellationToken());
Assert.True(result);
Assert.Single(context.Installations);
}
}
If I step through this test, when I get to the handler and inspect the app variable, the AppRevisions collection has automatically been populated. As a result, the test passes because the code that requires the AppRevisions collection to be populated can execute.
The expectation is that this test should actually fail, because I'm not telling EF to include those entities in the query.
I am using a Sqlite in memory database to create the database context for my unit tests and running .NET Core 2.2
I originally thought this was something to do with the changetracker. While disabling this does solve the immediate problem reported above, it creates a load of other problems so isn't a viable solution (and probably wouldn't be the correct one anyway)
Any suggestions gratefully received
For anyone who comes across this post in the future, the solution is as per the comments on the original question, to use separate contexts for seeding test data and getting the data later in the test:
[Fact]
public async void Handle_ShouldAddInstallationRecord_WhenDataIsValid()
{
Guid testGuid = Guid.NewGuid();
CreateInstallationCommand command = new CreateInstallationCommand(testGuid, "ABC", "abc#abc.com", null);
using (TestContextFactory contextFactory = new TestContextFactory())
{
using (TestContext seedContext = contextFactory.CreateTestContext())
{
seedContext.Apps.Add(new App() { Id = testGuid });
seedContext.AppRevisions.Add(new AppRevision() { Id = Guid.NewGuid(), AppId = testGuid, Status = AppRevisionStatus.Approved, IsListed = true });
await seedContext.SaveChangesAsync();
}
using (TestContext getContext = contextFactory.CreateTestContext())
{
CreateInstallationCommandHandler handler = new CreateInstallationCommandHandler(getContext);
CommandResult result = await handler.Handle(command, new CancellationToken());
Assert.True(result);
Assert.Single(getContext.Installations);
}
}
}
I have a simple hub that I am trying to write a test for with FakeItEasy and the verification of calling the client is not passing. I have the example working in a separate project that uses MOQ and XUnit.
public interface IScheduleHubClientContract
{
void UpdateToCheckedIn(string id);
}
public void UpdateToCheckedIn_Should_Broadcast_Id()
{
var hub = new ScheduleHub();
var clients = A.Fake<IHubCallerConnectionContext<dynamic>>();
var all = A.Fake<IScheduleHubClientContract>();
var id= "123456789";
hub.Clients = clients;
A.CallTo(() => all.UpdateToCheckedIn(A<string>.Ignored)).MustHaveHappened();
A.CallTo(() => clients.All).Returns(all);
hub.UpdateToCheckedIn(id);
}
I'm using Fixie as the Unit Test Framework and it reports:
FakeItEasy.ExpectationException:
Expected to find it once or more but no calls were made to the fake object.
The sample below works in XUnit & MOQ:
public interface IScheduleClientContract
{
void UpdateToCheckedIn(string id);
}
[Fact]
public void UpdateToCheckedIn_Should_Broadcast_Id()
{
var hub = new ScheduleHub();
var clients = new Mock<IHubCallerConnectionContext<dynamic>>();
var all = new Mock<IScheduleClientContract>();
hub.Clients = clients.Object;
all.Setup(m=>m.UpdateToCheckedIn(It.IsAny<string>())).Verifiable();
clients.Setup(m => m.All).Returns(all.Object);
hub.UpdateToCheckedIn("id");
all.VerifyAll();
}
I'm not sure what I've missed in the conversion?
You're doing some steps in a weird (it looks to me, without seeing the innards of your classes) order, and I believe that's the problem.
I think your key problem is that you're attempting to verify that all.UpdateToCheckedIn must have happened before even calling hub.UpdateToCheckedIn. (I don't know for sure that hub.UpdateToCheckedIn calls all.UpdateToCheckedIn, but it sounds reasonable.
There's another problem, where you configure clients.Setup to return all.Object, which happens after you assert the call to all.UpdateToCheckedIn. I'm not sure whether that's necessary or not, but thought I'd mention it.
The usual ordering is
arrange the fakes (and whatever else you need)
act, but exercising the system under test (hub)
assert that expected actions were taken on the fakes (or whatever other conditions you deem necessary for success)
I would have expected to see something more like
// Arrange the fakes
var all = A.Fake<IScheduleHubClientContract>();
var clients = A.Fake<IHubCallerConnectionContext<dynamic>>();
A.CallTo(() => clients.All).Returns(all); // if All has a getter, this could be clients.All = all
// … and arrange the system under test
var hub = new ScheduleHub();
hub.Clients = clients;
// Act, by exercising the system under test
var id = "123456789";
hub.UpdateToCheckedIn(id);
// Assert - verify that the expected calls were made to the Fakes
A.CallTo(() => all.UpdateToCheckedIn(A<string>.Ignored)).MustHaveHappened();
Edit: Context: I write a Silverlight application that accesses a Dynamics CRM 2011 via the Soap Service. I implemented a service for doing this. I want to write a unit test for this service now.
I want to write a unit test for the following method:
public async Task<List<string>> GetAttributeNamesOfEntity(string entityName)
{
// build request
OrganizationRequest request = new OrganizationRequest
{
RequestName = "RetrieveEntity",
Parameters = new ParameterCollection
{
new XrmSoap.KeyValuePair<string, object>()
{
Key = "EntityFilters",
Value = EntityFilters.Attributes
},
new XrmSoap.KeyValuePair<string, object>()
{
Key = "RetrieveAsIfPublished",
Value = true
},
new XrmSoap.KeyValuePair<string, object>()
{
Key = "LogicalName",
Value = "avobase_tradeorder"
},
new XrmSoap.KeyValuePair<string, object>()
{
Key = "MetadataId",
Value = new Guid("00000000-0000-0000-0000-000000000000")
}
}
};
// fire request
IAsyncResult result = OrganizationService.BeginExecute(request, null, OrganizationService);
// wait for response
TaskFactory<OrganizationResponse> tf = new TaskFactory<OrganizationResponse>();
OrganizationResponse response = await tf.FromAsync(result, iar => OrganizationService.EndExecute(result));
// parse response
EntityMetadata entities = (EntityMetadata)response["EntityMetadata"];
return entities.Attributes.Select(attr => attr.LogicalName).ToList();
}
My first approach was to call the actual CRM. This failed because I cannot authenticate. I asked a question about this here. My second approach is to mock the organization service and run the method against my the mock. Like this:
private bool _callbackCalled = false;
private SilverlightDataService _service;
private List<string> names;
[TestInitialize]
public void SetUp()
{
IOrganizationService organizationService = A.Fake<IOrganizationService>();
_service = new SilverlightDataService {OrganizationService = organizationService};
IAsyncResult result = A.Fake<IAsyncResult>();
A.CallTo(organizationService.BeginExecute(A<OrganizationRequest>.Ignored, A<AsyncCallback>.Ignored,
A<object>.Ignored)).WithReturnType<IAsyncResult>().Returns(result);
EntityMetadata entities = new EntityMetadata();
AttributeMetadata meta = new AttributeMetadata();
meta.LogicalName = "foobar";
entities.Attributes = new ObservableCollection<AttributeMetadata>();
entities.Attributes.Add(meta);
OrganizationResponse response = new OrganizationResponse();
response.Results = new ParameterCollection();
response["EntityMetadata"] = entities;
A.CallTo(() => result.IsCompleted).Returns(true);
A.CallTo(result.AsyncState).WithReturnType<object>().Returns(response);
A.CallTo(organizationService.EndExecute(result)).WithReturnType<OrganizationResponse>().Returns(response);
}
[TestMethod]
[Asynchronous]
public async void TestGetAttributeNamesOfEntity()
{
TaskFactory<List<string>> tf = new TaskFactory<List<string>>();
names = await tf.FromAsync(_service.GetAttributeNamesOfEntity("avobase_tradeorder"), CallbackFunction);
Assert.IsTrue(_callbackCalled);
Assert.IsNotNull(names);
}
/// <summary>
/// is used as callback for the method GetAttributeNamesOfEntity
/// </summary>
/// <param name="result"></param>
/// <returns></returns>
private List<string> CallbackFunction(IAsyncResult result)
{
_callbackCalled = true;
names = (List<string>) result.AsyncState;
return null;
}
I use FakeItEasy for mocking. When I execute this test (with ReSharper and AgUnit) it waits forever. I also tried this approach, but it did not work.
1) My assumption is that my mocks dont tell the await magic that the task is actually done. Why does the await never end? What do I have to do to fix this?
2) Is there maybe a better approach to do this?
Edit: I am using: VS 2012 Premium, ReSharper 7.1, Silverlight 5, AgUnit 0.7, .Net 4.5, FakeItEasy 1.13.1 installed via NuGet.
I'm using DotCover to check the unit test Coverage. Inside one of the method I return results from active directory in SearchResult however, I mocked the class but DotCover displays 0%
public virtual T SearchOneRecord(ISearchConfigurator configurator)
{
var record = (T)Activator.CreateInstance(typeof(T));
var searchResult = configurator.DirectorySearcher.FindOne();
if (searchResult != null)
{
AssignActiveDirectoryValue(searchResult, record);
}
return record;
}
[Test]
public void SearchOneRecord()
{
//Arrange
var configuratorMock = MockRepository.GenerateMock<ISearchConfigurator>();
var searchMock = MockRepository.GenerateStub<Searcher<NativeDs>>();
searchMock.Replay();
var nativeDs = new NativeDs() { PasswordAge = 100 };
searchMock.Expect(x => x.SearchOneRecord(configuratorMock)).Return(nativeDs);
//Act
var record = searchMock.SearchOneRecord(configuratorMock);
//Assert
Assert.AreEqual(nativeDs.PasswordAge, record.PasswordAge);
}
The test passes but since I'm new to RhinoMock (mocking in general) maybe there is an issue .
Any idea?
Correct me if I'm wrong but what you did here is defined mock and then tested if this mock works correctly? I don't think that's something you wanted to achieve. And of course it causes test to pass - mock is working correctly, but it is not testing you application code at all - hence 0% coverage.
What you want to do probably is to mock ISearchConfigurator instance and then pass that mock to method as a parameter.
[Test]
public void SearchOneRecord()
{
//Arrange
var configuratorMock = MockRepository.GenerateMock<ISearchConfigurator>();
var directorySearcherMock = MockRepository.GenerateMock<IDirectorySearcher>(); // please note I don't know exact type, so you need to ammend it
var returnValue = ... // initialize with types you expect DirectorySearcher to return
var searcher = new Searcher(); // initialize class you actually want to test
configurationMock.Replay();
configurationMock.Expect(x => x.DirectorySearcher).Return(directorySearcherMock);
directorySearcher.Expect(x => x.FindOne()).Return(returnValue);
searchMock.Expect(x => x.SearchOneRecord(configuratorMock)).Return(nativeDs);
//Act
var record = searcher.SearchOneRecord(configuratorMock);
//Assert
Assert.AreEqual(nativeDs.PasswordAge, record.PasswordAge);
}
Please note that I'm currently unable to test this code, but it should give you some directions into how it is supposed to be done.
Here's my scenario:
I'm working with a .NET MVC 4.0 project, with a repository (as you'd expect), and trying to implement the Moq/xUnit testing libraries into a .NET Unit Testing project.
I've got this far:
MVC Controller
private IHOLService _service;
public PolicyController(IHOLService service)
{
_service = service;
}
public ActionResult Index()
{
var policies = _service.GetAllPolicies(100, 0).ToList();
return View(policies);
}
Unit testing class
[Fact]
public void GetPolicies()
{
// Arrange
var mockService = new Mock<IHOLService>();
List<Policy> policy = new List<Policy>()
mockService.Setup(cr => cr.GetAllPolicies(10, 0)).Returns(policy);
var controller = new PolicyController(mockService.Object);
// policy here contains 0 results.
// Act
var result = (ViewResult)controller.Index();
var model = result.ViewData.Model; // equals 0.
// Assert
var listCategories = Assert.IsAssignableFrom<List<Policy>>(result.ViewData.Model);
// listCategories.Count equals 0 results.
Assert.Equal(10, listCategories.Count); // Thus always fails
}
My problem is that when the Controller is called directly, everything works fine, 100 policies are loaded.
However, when I run the test, 0 products are loaded, in which I'm guessing is a problem with the mocking calls somewhere down the line, potentially to do with the service initialisation. Has anyone ever had this before and can offer advice?
Also, am I correct to test my Service, rather than my Repository held at data layer?
Thanks in advance.
In your test code, you initialize policy to an empty list, then tell your mock service to return this empty list. To make the test load policies, you need to put some policy instances into your policy list.
I would write a test which looks something like this:
[Fact]
public void GetPolicies()
{
// Arrange
var mockService = new Mock<IHOLService>();
Policy expectedPolicy = new Policy(); // substitute for the real way you construct these
List<Policy> policy = new List<Policy>() { expectedPolicy };
mockService.Setup(cr => cr.GetAllPolicies(10, 0)).Returns(policy);
// Act
var result = (ViewResult)controller.Index();
var model = result.ViewData.Model; // equals 0.
// Assert
var listCategories = Assert.IsAssignableFrom<List<Policy>>(result.ViewData.Model);
Assert.Equal(expectedPolicy, listCategories.First());
}
But it really depends on what aspect of your code you are trying to unit test. From what I can see, this test simply confirms that you are storing the Policy objects as expected. You might write further tests for any logic that depends on the Policy instances themselves.