Assert that method was called in a unit test - c#

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);

Related

Moq checking if method is called with parameter from another call

I have the following function that I am trying to put under unit test
public MessageListDto GetMessageList(SimpleSearchCriteria criteria)
{
var messages = _repository.GetMessages(criteria, out int total);
return new MessageListDto(messages, total);
}
and the following is my test so far, in which I am able to determine that _repository.GetMessages is call with the correct parameters.
However, how do I test that the second line is tested properly, I need to test that
A new object of type MessageListDto is constructed with the two parameters returned from the line above
the newly constructed object is returned
[Test]
public void Test1()
{
int total = 10;
var searchCriteria = new SimpleSearchCriteria();
var mockRepo = new Mock<IMessageRepository>();
var messageService = new MessageService(mockRepo.Object);
messageService.GetMessageList(searchCriteria);
mockRepo.Verify(r => r.GetMessages(searchCriteria, out total), Times.Once);
mockRepo.Verity ??????????
}
As we have discussed in the comment section your goal is to test the returned messages is passed to the dto's constructor without any modification.
With your current code you can't do that because you are creating the DTO explicitly inside your method. So, you can't replace it with a spy.
Just to clarify some terminologies:
Dummy: simple code that returns bogus data
Fake: a working alternative which can take shortcuts
Stub: custom logic with predefined data
Mock: custom logic with expectations (interactive stub)
Shim: custom logic at run-time
Spy: interceptors to record calls
To be able to capture the arguments of the MessageListDto constructor call you need to introduce an other layer between your GetMessageList method and the constructor. (In other words indirection)
For the sake of simplicity let me assume that IMessageRepository's GetMessages returns a string array.
So, you can introduce an interface like this:
public interface IDtoProvider
{
public MessageListDto CreateMessageList(string[] messages, int total)
=> new MessageListDto(messages, total);
}
Here I have used C# 8's interface default implementation feature
It can be further shortened with C# 9's target-typed new expression feature
If you are using older C# version then you need to separate the interface and the default implementation from each other
Now lets amend your MessageService to receive a IDtoProvider instance via its constructor
class MessageService
{
private readonly IMessageRepository _repository;
private readonly IDtoProvider _dtoProvider;
public MessageService(IMessageRepository repository, IDtoProvider dtoProvider)
=> (_repository, _dtoProvider) = (repository, dtoProvider);
public MessageListDto GetMessageList(SimpleSearchCriteria criteria)
{
var messages = _repository.GetMessages(criteria, out int total);
return _dtoProvider.CreateMessageList(messages, total);
}
...
}
Here I've took advantage of ValueTuple's deconstruct capability
With these in our hand we can write a unit test like this:
//Arrange - Repo
string[] messages = new[] { "OnlyElement" };
int total = 10;
var mockRepo = new Mock<IMessageRepository>();
mockRepo
.Setup(repo => repo.GetMessages(It.IsAny<SimpleSearchCriteria>(), out total))
.Returns(messages);
//Arrange - Provider
var dto = new MessageListDto(messages, total);
string[] messagesArgument = null;
int totalArgument = -1;
var mockProvider = new Mock<IDtoProvider>();
mockProvider
.Setup(provider => provider.CreateMessageList(It.IsAny<string[]>(), It.IsAny<int>()))
.Callback<string[], int>((messages, total) => (messagesArgument, totalArgument) = (messages, total))
.Returns(dto);
//Arrange - SUT
var searchCriteria = new SimpleSearchCriteria();
var sut = new MessageService(mockRepo.Object, mockProvider.Object);
//Act
sut.GetMessageList(searchCriteria);
//Assert - Repo
mockRepo.Verify(r => r.GetMessages(searchCriteria, out total), Times.Once);
//Assert - Provider
Assert.Equal(messages, messagesArgument);
Assert.Equal(total, totalArgument);
I've defined how should the IMessageRepository mock behave
I've defined how should the IDtoProvider mock behave
2.1 I've used here the Callback method to capture the calling argument
2.2 If you perform multiple calls against your mocked method then please consider to use Capture.In
I've instantiated a MessageService (which is our system under test) with the mock objects
I've called the GetMessageList inside the Act phase
I've made assertion against the repo mock call
I've made assertion against the calling parameters of the CreateMessageList
6.1 Here I have used xunit's assertion
The first step is to setup the MessageService mock, so that it returns something deterministic and then in the second step you verify that that has been used to construct your MessageListDto.
[Test]
public void Test1()
{
// arrange
int total = 10;
var searchCriteria = new SimpleSearchCriteria();
var messages = new [] {"message1", "message2"} // or similar
var mockRepo = new Mock<IMessageRepository>();
// or similar, I am not quite certain as to the specific syntax. Especially wrt. out parameters. Check the documentation.
mockRepo.Setup(x => x.GetMessages(It.IsAny<SimpleSearchCriteria>(), It.IsAny<int>())).Returns(messages);
var messageService = new MessageService(mockRepo.Object);
// act
var result = messageService.GetMessageList(searchCriteria);
// assert
mockRepo.Verify(r => r.GetMessages(searchCriteria, out total), Times.Once);
// or similar; here you might want to check out FluentAssertions as #Peter Csala suggested
Assert.Equal(result.Messages, messages);
}
What's missing from previous answers is that whenever possible, you should set up the mocked method with the exact parameters, that you expect it to receive. In other words set up the method with concrete values instead of It.IsAny<>(). In such case you won't have to verify the method later at all. (Unless it's critical to test, how many times a method is called). Simply, if mocked GetMessages receives different arguments than expected, it will return null, set total to 0 and your test will fail. Having the mocked methods set up properly, you can now focus on verifying what GetMessageList returns, which is the purpose of this unit test.
[Test]
public void Test1()
{
int total = 10;
var messages = new[] {new Message()};
var searchCriteria = new SimpleSearchCriteria();
var mockRepo = new Mock<IMessageRepository>();
mockRepo.Setup(_ => _.GetMessages(searchCriteria, out total))
.Returns(messages);
var messageService = new MessageService(mockRepo.Object);
var dto = messageService.GetMessageList(searchCriteria);
Assert.AreSame(messages, dto.Messages);
Assert.AreEqual(total, dto.Total);
}

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().

C# FakeItEasy and Method Chaining: Only First Call Is Recognized

I have a call to a factory interface that creates an IMachine in a command handler. This returned IMachine from the factory has methods that can be chained together to create itself inside of a builder class. The problem I am running into with FakeItEasy right now is that it only recognized the first call (which is WithSpeeds) unless I configure every method call to return a fake IMachine. Is there a way not to configure every single call or have FakeItEasy recognize every method call on the chain? I know I must be doing something incorrect because if i use OrderAssertions, and fail the order on purpose without setting up my fake machine, it shows calls were made to all the methods. Thanks for the help.
Part of the Command Handler's Method
public void Handle(FooCommand commandParm)
{
var entity = new Entity.Builder
{
Machine = _factory.CreateMachine(commandParm.MachineName)
.WithSpeeds(commandParm.ProcessingSpeed, commandParm.StartupSpeed, commandParm.ShutDownSpeed)
.WithOils(commandParm.Lubrication, commandParm.FinishingOil)
};
}
Test
[TestMethod]
public void HandleSetMachineSettings_should_build_machine()
{
// Arrange
var settings = CommandUtilities.ReturnFooCommand();
var _factory = A.Fake<IMachineFactory>();
var machine = A.Fake<IMachine>();
A.CallTo(() => _factory.CreateMachine(settings.MachineName)).Returns(machine);
// Act
_handler.Handle(settings);
// Assert
machine.Should().NotBeNull();
A.CallTo(machine).Where(x => x.Method.Name.Equals("set_MachineNumber")).WhenArgumentsMatch(arg => arg.Get<int>(0) == settings.MachineNumber).MustHaveHappened(Repeated.Exactly.Once);
A.CallTo(() => machine.WithSpeeds(commandParm.ProcessingSpeed, commandParm.StartupSpeed, commandParm.ShutDownSpeed)).MustHaveHappened(Repeated.Exactly.Once);
A.CallTo(() => machine.WithOils(commandParm.Lubrication, commandParm.FinishingOil)).MustHaveHappened(Repeated.Exactly.Once);
}
I take it that WithSpeeds and WithOils both return an IMachine, yes?
The problem is:
_factory.CreateMachine returns one IMachine, machine from your setup
machine.WithSpeeds returns a fake IMachine that FakeItEasy makes up. This is not machine, but is a different fake, call it "machine2"
machine2.WithOils returns yet another fake machine
Your Assert block suggests that you expected the same machine to be returned at each step of the builder chain. Try inserting
A.CallTo(machine)
.WithReturnType<IMachine>()
.Returns(machine);
after A.CallTo(() => _factory.CreateMachine()).Returns(machine);
That way machine will keep returning itself, and the appropriate properties will be set on it and whatnot.

Rhino Mocks, how can I perform an action after setting a Stub property

I have a simple requirement, but I seem to be struggling.
I have created a stub that mocks an interface that includes a Property :
public interface IMockIRuleRuningViewModel : IRuleRunningViewModel
{
int Id { get; set; }
}
And the mock is :
var mock = MockRepository.GenerateStub<IMockIRuleRuningViewModel>();
Now I want to mock an action that I would have put in a setter for this Property, and here is my attempt :
mock.Stub(x => x.Id).WhenCalled(
o =>
{
var engine = new RulesEngine(mock);
mock.ProcessRuleEngineResults(engine.RunRule("Id"));
});
But I keep getting this Exception :
You are trying to set an expectation on a property that was defined to use PropertyBehavior.
Instead of writing code such as this: mockObject.Stub(x => x.SomeProperty).Return(42);
You can use the property directly to achieve the same result: mockObject.SomeProperty = 42;
The following works for me:
HttpResponseBase response = MockRepository.GenerateMock<HttpResponseBase>();
// stub the getter
response.Stub(r => r.StatusCode).Return((int)HttpStatusCode.OK);
// Stub the setter
response.Stub(r => r.StatusCode = Arg<int>.Is.Anything).WhenCalled( o =>
{
Console.WriteLine("called");
});
Since what I'm actually trying to do is model the case where you can get but not set the status code (because headers have already been sent), I don't do WhenCalled(), I do this:
response.Stub(r => r.StatusCode = Arg<int>.Is.Anything)
.Throw(new HttpException("Server cannot set status after HTTP headers have been sent"));
You have to use MockRepository.GenerateMock not MockRepository.GenerateStub. I don't know why.
If you want to verify the behavior of the SUT (system under test), you should use a mock with the appropriate expectation, and verify that. If you want just to pass a value that may need to act in a certain way, but isn't the focus of this test, you will use a stub (stub will not cause a test to fail).
I assume that you are testing RulesEngine in this test (because it is only real object I see). Here is a sample test, which verifies behavior of engine, when "Id" rule was executed:
// Arrange
var model = MockRepository.GenerateMock<IMockIRuleRuningViewModel>();
model.Expect(m => m.ProcessEngineResults(42));
RulesEngine engine = new RulesEngine(model);
// Act
engine.RunRule("Id");
// Assert
model.VerifyAllExpectations();

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