Assert that multiple unordered calls occur before a final call - c#

I have a service that
Makes a call to each registered class that implements a specific interface (IUnorderedService)
Then makes a final call to another service (IFinalService)
I want to write a test that asserts that my service makes a call to each IUnorderedService in no specific order, and then makes a call to the IFinalService. Using FakeItEasy, is there any way to do this?
My implementation looks like this (much simplified):
public class MyService
{
private readonly IFinalService finalService;
private readonly IEnumerable<IUnorderedService> unorderedServices;
public MyService(
IFinalService finalService,
IEnumerable<IUnorderedService> unorderedServices)
{
this.finalService = finalService;
this.unorderedServices = unorderedServices;
}
public void Execute()
{
foreach (var unorderedService in this.unorderedServices)
{
unorderedService.Execute();
}
this.finalService.Execute();
}
}
And my test method would look something like this
public void ShouldCallUnorderedService_BeforeCallingFinalService()
{
// Arrange
...
// Act
myService.Execute();
// Assert
foreach (var unorderedService in unorderedServices)
{
A.CallTo(() => unorderedService.Execute()).MustHaveHappenedOnceExactly();
}
// Should be asserted that this call occurs after all of the above calls have occurred.
A.CallTo(() => finalService.Execute()).MustHaveHappenedOnceExactly();
}
I have played around with the A.CallTo().Then() syntax which works great for most purposes, but I don't see a way assert occurrence of multiple unordered calls prior to an ordered call.

There's nothing directly built into FakeItEasy for this scenario. One option would be to intercept the calls as they are made. Then you could verify the order was as you wanted. The call-intercepting feature is (I believe) infrequently used, so this might be less understandable, but could be worth pursuing.
Then I thought about leveraging the "callback" or Invokes facility on a Fake to record whether a fake call was supposed to be final or not, then verify the setting at the end of the test:
[Fact]
public void ShouldCallUnorderedService_BeforeCallingFinalService()
{
var lastKindOfService = "none";
var unorderedServices = new [] {
A.Fake<IUnorderedService>(),
A.Fake<IUnorderedService>(),
A.Fake<IUnorderedService>(),
};
foreach (var unorderedService in unorderedServices)
{
A.CallTo(() => unorderedService.Execute()).Invokes(() => lastKindOfService = "unordered");
}
var finalService = A.Fake<IFinalService>();
A.CallTo(() => finalService.Execute()).Invokes(() => lastKindOfService = "final");
var service = new MyService(finalService, unorderedServices);
service.Execute();
foreach (var unorderedService in unorderedServices)
{
A.CallTo(() => unorderedService.Execute()).MustHaveHappenedOnceExactly();
}
A.CallTo(() => finalService.Execute()).MustHaveHappenedOnceExactly();
lastKindOfService.Should().Be("final");
}
Of course this could be prettied up with a helper method or enums for the state. And if there's any asynchrony, you might want to serialize the updates.

You can put the A.CallTo().Then() into your foreach
foreach (var unorderedService in unorderedServices)
{
A.CallTo(() => unorderedService.Execute()).MustHaveHappenedOnceExactly()
.Then(A.CallTo(() => finalService.Execute()).MustHaveHappenedOnceExactly()
}
So you are checking that each call to the unordered service happened before the call to the final service. Unfortunately this is not a bulk check, but I think the end result will still prove code correctness

Related

How to correctly assert MustHaveHappend(object) in fake it easy

I am having a test method that asserts if the CreateClient method of the client account repository has been called. Please See the test bellow.
[TestMethod]
public void CreateNewBasicClientAccount_NewBasicClient_CreatesNewClientBasicClient()
{
// Arrange
var clientAccountToCreate = new ClientAccount
{
Name = "Name",
};
var clientAccountToCreateDto = AutoMapper.Mapper.Map<ClientAccount, ClientAccountDto>(clientAccountToCreate);
var clientAccountRepository = A.Fake<IClientAccountRepository>();
var clientAccountManager = new ClientAccountManager(clientAccountRepository);
// Act
clientAccountManager.CreateClient(clientAccountToCreate);
// Assert
A.CallTo(
() => clientAccountRepository.CreateClient(A<ClientAccountDto>.That.IsNotNull<ClientAccountDto>()))
.MustHaveHappened();
A.CallTo(
() => clientAccountRepository.CreateClient(A<ClientAccountDto>.Ignored))
.MustHaveHappened();
A.CallTo(
() => clientAccountRepository.CreateClient(clientAccountToCreateDto))
.MustHaveHappened();
}
The Act portion of my ClientAccountManager class in the test is calling the CreateClient method of the repository
public void CreateClient(ClientAccount client)
{
var clientDto = AutoMapper.Mapper.Map<ClientAccount, ClientAccountDto>(client);
_clientAccountRepository.CreateClient(clientDto);
}
The first two asserts in the test pass, but the more specific 3rd assert fails with result message
InterfaceNameSpace.IClientAccountRepository.CreateClient(clientDto: DtoNameSpace.ClientAccountDto)
Expected to find it at least once but found it #0 times among the calls:
Both the ClientAccount and ClientAccountDto classes have the exact same properties. Input in getting the failed assert to pass would be appreciated as the code is wired up for it to pass but it fails.
This is because the actual ClientAccountDto that is passed to the method is not the same instance as the one you create in your test, so they're not considered equal.
There are several options to solve this:
override the Equals method in ClientAccountDto (not ideal, since you normally wouldn't need this for a DTO)
inject an IMapper into ClientAccountManager, instead of using the static Mapper class, and configure the IMapper to return a specific instance of ClientAccountDto
test specific properties of the ClientAccountDto, like this:
A.CallTo(
() => clientAccountRepository.CreateClient(A<ClientAccountDto>.That.Matches(x => x.Name == "Name")))
.MustHaveHappened();
Unrelated note: you don't need to specify the type again in A<ClientAccountDto>.That.IsNotNull<ClientAccountDto>(), you can just write A<ClientAccountDto>.That.IsNotNull().

Rhino Mock Test Expected #1, Actual #0 - error

I'm newbie working with Rhino Mock and I'm getting this error that I cannot understand why. Here the test
public void TestGet()
{
var installationReference = new Guid("21D7D135-6E9E-4F92-8313-873CA3ABDCD8");
var study = MockRepository.GenerateMock<IStudy>();
var installation = MockRepository.GenerateMock<IInstallation>();
var license = MockRepository.GenerateMock<ILicense>();
var participant = MockRepository.GenerateMock<IStudyParticipant>();
var clinicalPartner = MockRepository.GenerateMock<IClinicalPartner>();
clinicalPartner.Stub(c => c.FirstName).Return("John");
clinicalPartner.Stub(c => c.LastName).Return("Doe");
installation.Stub(i => i.Reference).Return(installationReference);
license.Stub(l => l.Installations).Return(new List<IInstallation> { installation });
participant.Stub(p => p.Licenses).Return(new List<ILicense> { license });
participant.Stub(p => p.ClinicalPartner).Return(clinicalPartner);
participant.Stub(p => p.ClinicalPartnerStatus).Return(ClinicalPartnerStatus.Active);
study.Stub(s => s.Description).Return("Test WebAPI");
study.Stub(s => s.Participants).Return(new List<IStudyParticipant> { participant });
repository.Stub(r => r.Query(Arg<GetStudiesByInstallationReference>.Matches(s => s.InstallationReference.Equals(installationReference))))
.Return(new DummyResult<IStudy>(study));
repository.Expect(r => r.Query(Arg<GetStudiesByInstallationReference>.Matches(s => s.InstallationReference.Equals(installationReference)))).Return(new DummyResult<IStudy>(study)).Repeat.Once();
repository.VerifyAllExpectations();
}
My GetStudiesByInstallationReference.cs
public class GetStudiesByInstallationReference : IQuery<IStudy>
{
public Guid InstallationReference { get; set; }
public GetStudiesByInstallationReference(Guid installationReference)
{
InstallationReference = installationReference;
}
public IQueryResult<IStudy> Execute(ISession session)
{
var criteria = session.CreateCriteria<IStudy>();
criteria.CreateAlias("participants", "p");
criteria.CreateAlias("p.licenses", "l");
criteria.CreateAlias("l.installations", "i");
criteria.Add(Restrictions.Eq("i.Reference", InstallationReference));
criteria.Add(Restrictions.Eq("Status", StudyStatus.Approved));
criteria.Add(Restrictions.Eq("p.ClinicalPartnerStatus", ClinicalPartnerStatus.Active));
criteria.Add(Restrictions.Le("StartDate", DateTime.Now));
criteria.Add(Restrictions.Or(
Restrictions.IsNull("EndDate"),
Restrictions.Gt("EndDate", DateTime.Now)));
return new CriteriaResult<IStudy>(criteria);
}
}
I want to test GetStudiesByInstallationReference was called one time.
What am I doing wrong?...it should pass the test as the Expect clause is the same used in the Stub but I still got the exception
Expected #1, Actual #0.
Anybody could help me with this?
Thanks in advance
I want to test GetStudiesByInstallationReference was called one time.
GetStudiesByInstallationReference is a type, and not a method that you expect to be called.
repository
.Expect(r => r.Query(Arg<GetStudiesByInstallationReference>.Matches(s => s.InstallationReference.Equals(installationReference))))
.Return(new DummyResult<IStudy>(study)).Repeat.Once();
This line from your code is setting up an expectation on the repository mock. It expects that the Query() method is called with a parameter of type GetStudiesByInstallationReference that has the correct installation reference GUID as a property. If this method isn't called with the correct parameter, you will get the error you describe when calling repository.VerifyAllExpectations().
It looks like your test is missing the actual call to the SUT i.e. the "Act" in Arrange/Act/Assert. Simply put, you need to execute some code that will cause the method on your repository to be called as you expect (or change the test).

Unit Test Using Moq

I am unit-testing an async method that returns a List<T>. This method has a dependency on a mapping class/interface. In my unit-test, I am mocking the mapping class using moq. The test runs okay, and the returned list has items, but the values of the items is null. I think the problem is because I haven't stubbed-out the mapping classes methods properly. I don't have a lot of experience with testing, so any guidance is appreciated.
Test Method:
[TestMethod]
[TestCategory("CSR.Data.Tests.Services.ServiceSearchTest")]
public void SearchAccount()
{
// Arrange
var mapper = new Mock<CSR.Data.Mapping.Interfaces.IMapper<Account, AccountDTO>>();
mapper.Setup(i => i.Initialize());
mapper.Setup(i => i.ToDomain(It.IsAny<AccountSearchResult>())).Returns(It.IsAny<Account>);
mapper.Setup(i => i.DomainToDto(It.IsAny<Account>())).Returns(It.IsAny<AccountDTO>);
var service = new ServiceSearch(null,mapper.Object);
string accountNumber = "123";
string accountName = "";
// Act
var results = service.SearchAccount(accountNumber, accountName);
// Assert
Assert.IsTrue(results.Result.Count >= 1);
}
Method/Class That I'm Testing:
public class ServiceSearch : IServiceSearch
{
public ServiceSearch(IMapper<Claim, ClaimDTO> claimMapper, IMapper<Account, AccountDTO> accountMapper)
{
_claimMapper = claimMapper;
_accountMapper = accountMapper;
}
public async Task<List<AccountDTO>> SearchAccount(string accountNumber, string accountName)
{
var accounts = new List<Account>();
var accountDTOs = new List<AccountDTO>();
var results = await Task.Run(() => base.AccountSearch(accountNumber, accountName).Result);
if (results != null && results.Count > 0)
{
//Map DH to Domain
_accountMapper.Initialize();
foreach (AccountSearchResult result in results)
{
accounts.Add(_accountMapper.ToDomain(result));
}
//Map Domain to DTO
foreach (Account account in accounts)
{
accountDTOs.Add(_accountMapper.DomainToDto(account));
}
}
return accountDTOs;
}
}
This isn't the best place to use a Mock object because you are going to spend a lot of time writing your test objects and mock results. The issue with the setup call is that you haven't configured anything to send back in the result. A correct example would be:
// you would fully configure this object
AccountDTO expectedResult = new AccountDTO();
mapper.Setup(i => i.ToDomain(It.IsAny<AccountSearchResult>())).Returns(expectedResult);
Now you can use the setup to configure different accountDTOs for different inputs.
You call also configure a callback to generate the account at test time:
mapper.Setup(i => i.ToDomain(It.IsAny<AccountSearchResult>())).Returns<AccountSearchResult>(sr => {
// build and return your dto here
});
However, unless your mapper is expensive to run or create, I think you'd better off just ensure that it is fully tested and acceptable and then use it to go ahead and generate the DTOs directly instead of trying to mock it out.
You don't actually setup an object in the ".Returns" call. You need to make sure to setup the ".Returns" to actually have an object with values.

Assert that method was called in a unit test

I want to assert that a call on my real object (system under test) was called. Here is my test
// Arrange
var contextFactory = A.Fake<IContextFactory>();
var db = A.Fake<IDatabase>();
A.CallTo(() => contextFactory.GetContext()).Returns(db);
var vm = new MainViewModel(contextFactory);
// Act
vm.Loaded();
// Assert
A.CallTo(() => vm.LoadModels(db)).MustHaveHappened();
I'm getting an ArgumentException that says "The specified object is not recognized as a fake object." How do I test that the LoadModels() method in my MainViewModel gets called from the Loaded() method?
EDIT
The reason I'm doing it this way is because the Loaded() method calls a bunch of other methods when the app starts and I don't want to have to setup all the other stuff for each test, I just want to make sure that all the proper methods get called and then test them individually. I'm open to suggestion for a better way of going about this.
Here are the Loaded and LoadModels methods
internal virtual void Loaded()
{
using (var db = _contextFactory.GetContext())
{
LoadModels(db);
// bunch of other method calls
}
}
internal virtual void LoadModels(IDatabase db)
{
Models = new ObservableCollection<Model>(db.Models);
}
It looks like you're verifying a method (vm.LoadModels) that isn't part of the fake (db). You can only verify methods on a fake, not methods that happen to take the fake as an argument.
I ended up moving the functionality of LoadModels() to another class that implements IStartupDataLoader and then I was able to test it like this
// Arrange
var sdl = A.Fake<IStartupDataLoader>();
var exp = A.Fake<ObservableCollection<Model>>();
A.CallTo(() => sdl.LoadModels()).Returns(exp);
var sut = new MainViewModel(sdl);
// Act
sut.Loaded();
// Assert
Assert.That(exp == sut.Models);

Proper way to verify parameters being passed to a Mock are set as expected

Is it acceptable to do asserts in your callbacks if you later verify that the methods were called? Is this the preferred way of making sure my mock is getting the expected parameters passed to it, or should I set a local variable in my callback and do the asserts on that instance?
I have a situation where I have some logic in a Presenter class that derives values based on inputs and passes them to a Creator class. To test the logic in the Presenter class I want to verify that the proper derived values are observed when the Creator is called. I came up with the example below that works, but I'm not sure if I like this approach:
[TestFixture]
public class WidgetCreatorPresenterTester
{
[Test]
public void Properly_Generates_DerivedName()
{
var widgetCreator = new Mock<IWidgetCreator>();
widgetCreator.Setup(a => a.Create(It.IsAny<Widget>()))
.Callback((Widget widget) =>
Assert.AreEqual("Derived.Name", widget.DerivedName));
var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
presenter.Save("Name");
widgetCreator.Verify(a => a.Create(It.IsAny<Widget>()), Times.Once());
}
}
I'm concerned because without the Verify call at the end, there is no guarantee that the assert in the callback would be invoked. Another approach would be to set a local variable in the callback:
[Test]
public void Properly_Generates_DerivedName()
{
var widgetCreator = new Mock<IWidgetCreator>();
Widget localWidget = null;
widgetCreator.Setup(a => a.Create(It.IsAny<Widget>()))
.Callback((Widget widget) => localWidget = widget);
var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
presenter.Save("Name");
widgetCreator.Verify(a => a.Create(It.IsAny<Widget>()), Times.Once());
Assert.IsNotNull(localWidget);
Assert.AreEqual("Derived.Name", localWidget.DerivedName);
}
I feel that this approach is less error prone since it is more explicit, and it's easier to see that the Assert statements will be called. Is one approach preferable to the other? Is there a simpler way to test the input parameter passed to a mock that I'm missing?
In case it is helpful, here is the rest of the code for this example:
public class Widget
{
public string Name { get; set; }
public string DerivedName { get; set; }
}
public class WidgetCreatorPresenter
{
private readonly IWidgetCreator _creator;
public WidgetCreatorPresenter(IWidgetCreator creator)
{
_creator = creator;
}
public void Save(string name)
{
_creator.Create(
new Widget { Name = name, DerivedName = GetDerivedName(name) });
}
//This is the method I want to test
private static string GetDerivedName(string name)
{
return string.Format("Derived.{0}", name);
}
}
public interface IWidgetCreator
{
void Create(Widget widget);
}
EDIT
I updated the code to make the second approach I outlined in the question easier to use. I pulled creation of the expression used in Setup/Verify into a separate variable so I only have to define it once. I feel like this method is what I'm most comfortable with, it's easy to setup and fails with good error messages.
[Test]
public void Properly_Generates_DerivedName()
{
var widgetCreator = new Mock<IWidgetCreator>();
Widget localWidget = null;
Expression<Action<IWidgetCreator>> expressionCreate =
(w => w.Create(It.IsAny<Widget>()));
widgetCreator.Setup(expressionCreate)
.Callback((Widget widget) => localWidget = widget);
var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
presenter.Save("Name");
widgetCreator.Verify(expressionCreate, Times.Once());
Assert.IsNotNull(localWidget);
Assert.AreEqual("Derived.Name", localWidget.DerivedName);
}
What I do is do the Verify with matches in keeping with AAA. And becuase of this the Setup is not required. You can inline it but I separated it out to make it look cleaner.
[Test]
public void Properly_Generates_DerivedName()
{
var widgetCreator = new Mock<IWidgetCreator>();
var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
presenter.Save("Name");
widgetCreator.Verify(a => a.Create(MatchesWidget("Derived.Name"));
}
private Widget MatchesWidget(string derivedName)
{
return It.Is<Widget>(m => m.DerivedName == derivedName);
}
Because of the way your code is structured, you're kind of forced to test two things in one unit test. You're testing that A) your presenter is calling the injected WidgetCreator's create method and B) that the correct name is set on the new Widget. If possible, it'd be better if you can somehow make these two things two separate tests, but in this case I don't really see a way to do that.
Given all that, I think the second approach is cleaner. It's more explicit as to what you're expecting, and if it fails, it'd make perfect sense why and where it's failing.
Just to elaborate on #rsbarro's comment - the Moq failure error message:
Expected invocation on the mock at least once, but was never performed
... is less than helpful for complex types, when determining exactly which condition actually failed, when hunting down a bug (whether in the code or unit test).
I often encounter this when using Moq Verify to verify a large number of conditions in the Verify, where the method must have been called with specific parameter values which are not primitives like int or string.
(This is not typically a problem for primitive types, since Moq lists the actual "performed invocations" on the method as part of the exception).
As a result, in this instance, I would need to capture the parameters passed in (which to me seems to duplicate the work of Moq), or just move the Assertion inline with Setup / Callbacks.
e.g. the Verification:
widgetCreator.Verify(wc => wc.Create(
It.Is<Widget>(w => w.DerivedName == "Derived.Name"
&& w.SomeOtherCondition == true),
It.Is<AnotherParam>(ap => ap.AnotherCondition == true),
Times.Exactly(1));
Would be recoded as
widgetCreator.Setup(wc => wc.Create(It.IsAny<Widget>(),
It.IsAny<AnotherParam>())
.Callback<Widget, AnotherParam>(
(w, ap) =>
{
Assert.AreEqual("Derived.Name", w.DerivedName);
Assert.IsTrue(w.SomeOtherCondition);
Assert.IsTrue(ap.AnotherCondition, "Oops");
});
// *** Act => invoking the method on the CUT goes here
// Assert + Verify - cater for rsbarro's concern that the Callback might not have happened at all
widgetCreator.Verify(wc => wc.Create(It.IsAny<Widget>(), It.Is<AnotherParam>()),
Times.Exactly(1));
At first glance, this violates AAA, since we are putting the Assert inline with the Arrange (although the callback is only invoked during the Act), but at least we can get to the bottom of the issue.
Also see Hady's idea of moving the 'tracking' callback lambda into its own named function, or better still, in C#7, this can be moved to a Local Function at the bottom of the unit test method, so the AAA layout can be retained.
Building on top of StuartLC's answer in this thread, you follow what he is suggesting without violating AAA by writing an "inline" function that is passed to the Verify method of a mock object.
So for example:
// Arrange
widgetCreator
.Setup(wc => wc.Create(It.IsAny<Widget>(), It.IsAny<AnotherParam>());
// Act
// Invoke action under test here...
// Assert
Func<Widget, bool> AssertWidget = request =>
{
Assert.AreEqual("Derived.Name", w.DerivedName);
Assert.IsTrue(w.SomeOtherCondition);
Assert.IsTrue(ap.AnotherCondition, "Oops");
return true;
};
widgetCreator
.Verify(wc => wc.Create(It.Is<Widget>(w => AssertWidget(w)), It.Is<AnotherParam>()), Times.Exactly(1));

Categories