How to test a factory provided class is used - c#

I have a section of code that calls a factory, and then uses the returned object.
var myServiceObject = factoryService.GetTheObject(myParam);
myServiceObject.DoSomeWork(someData, moreData); // returns void
I'm writing a test with Automock where I want to verify that I call the factory and that I attempt to use the object.
For mocking the factory I'm assuming I need it to return an instance?
mock.Mock<IFactoryService>().Setup(x => x.GetTheObject(It.IsAny<paramType>()))
.Returns({insertSomething});
I was going to use a mock object, and do something like this:
mock.Mock<IMyService>().Setup(x => x.DoSomeWork(...));
var mockOfMyService = mock.Provide<IMyService>(new MockOfMyService()); // MockOfMyService inherits from IMyService
mock.Mock<IFactoryService>().Setup(x => x.GetTheObject(It.IsAny<paramType>()))
.Returns(mockOfMyService);
...
mock.Mock<IFactoryService>().Verify(...); // This passes
mock.Mock<IMyService>().Verify(x => x.DoSomeWork(...), Times.Once); // This errors
But I'm getting an invalid cast exception on the verify. Any good examples out there? What am I doing wrong?

So, for this one, I received some help outside of SO. Here's what worked for me:
mock.Mock<IMyService>().Setup(x => x.DoSomeWork(...));
var mockOfMyService = mock.Mock<IMyService>().Object; // Slight change here
mock.Mock<IFactoryService>().Setup(x => x.GetTheObject(It.IsAny<paramType>()))
.Returns(mockOfMyService);
...
mock.Mock<IFactoryService>().Verify(...); // This passes
mock.Mock<IMyService>().Verify(x => x.DoSomeWork(...), Times.Once); // And now this passes

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

Omit method execution of stubbed object

I have a code listed below inside one of my method which I would like to test:
using (var obj1 = provider.GetObj1Instance())
{
/* Do some stuff */
obj1.DoAction();
}
provider is an object which I mocked:
provider = MockRepository.GenerateMock<IProvider>();
but method GetObj1Instance() returns concrete-typed object. Right now after mocking I get NullRefrenceException, because method GetObj1Instance() from mocked provider returns null.
Then I stubbed obj1:
var stubbedObj1 = MockRepository.GenerateStub<Obj1>();
provider.Stub(o => o.GetObj1Instance()).Return(stubbedObj1);
but it's not sufficient, because inside obj1.DoAction(); there is reference to private variable which throws NullReferenceException
During test execution, I would like to not execute obj1.DoAction() or just to register that it was invoked. How to achieve that?
This line below doesn't prevent DoAction method from original execution.
stubbedObj1.Stub(u => u.DoAction()).Do(new Action(() => { }));

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

Setting up moq and verifying that a method was called

Using Microsoft Test Framework and Moq I'm trying to verify if a log4net method was called.
[TestMethod()]
public void Log_Info_When_Stuff_Is_Done()
{
SampleClass sampleObject = new SampleClass();
Mock<log4net.ILog> logMockObject = new Mock<log4net.ILog>();
sampleObject.Log = logMockObject.Object;
sampleObject.DoStuffAndLogInfo();
logMockObject.Verify(moqLog => moqLog.Info("do stuff got called"), Times.AtLeastOnce());
}
I get an exception on Verify call saying that
Expected invocation on the mock at least once, but was never
performed: moqLog => moqLog.Info("do stuff got called") No setups
configured. No invocations performed.
What am I doing wrong?
update the problem was with a getter for SampleClas.Log property. I was always returning LogManager.GetLogger(...); even when the property was already set to a ILogProxy. I was under impression that the property's get accessor won't be called because I've set up a proxy like so sampleObject.Log = logMockObject.Object;
Right now Moq is verifying that DoStuffAndLogInfo calls Info with the exact string "do stuff got called". If it's actually calling Info with a different argument, and you don't care what the actual argument is, use the following instead:
logMockObject.Verify(moqLog => moqLog.Info(It.IsAny<string>()), Times.AtLeastOnce());
The test is correctly set up.
Check your sut to see if Log.Info actually gets called inside the DoStuffAndLogInfo method.
This doesn't look to be the original poster's problem, but in my case I had a very similar error message. It was due to my .Verify() call before the actual execution. For example, this is wrong:
SampleClass sampleObject = new SampleClass();
Mock<log4net.ILog> logMockObject = new Mock<log4net.ILog>();
logMockObject.Verify(moqLog => moqLog.Info(It.IsAny<string>()), Times.AtLeastOnce());
sampleObject.Log = logMockObject.Object;
sampleObject.DoStuffAndLogInfo();
....but this is right:
SampleClass sampleObject = new SampleClass();
Mock<log4net.ILog> logMockObject = new Mock<log4net.ILog>();
sampleObject.Log = logMockObject.Object;
sampleObject.DoStuffAndLogInfo();
logMockObject.Verify(moqLog => moqLog.Info(It.IsAny<string>()), Times.AtLeastOnce());

Categories