Rhino AutoMocker and Stubs - rhino-mocks

I am using Joshua Flanagan article “Auto mocking Explained” as a guide. In the article there is a section called “The same tests, with automocker would look like this”. I used this information to build code to run the automocker.
As you can see below answer is a list returned from the BLL. Answer does have one row in it; however, all fields are null. So the test for boo fails. Any tips and hints would be greatly appreciated.
[Test]
public void GetStaffListAndRolesByTeam_CallBLLWithDALStub()
{
// Build List<> data for stub
List<StaffRoleByTeamCV> stubData = new List<StaffRoleByTeamCV>();
StaffRoleByTeamCV stubRow = new StaffRoleByTeamCV();
stubRow.Role = "boo";
stubRow.StaffId = 12;
stubRow.StaffName = "Way Cool";
stubData.Add(stubRow);
// create the automocker
var autoMocker = new RhinoAutoMocker<PeteTestBLL>();
// get instance of test class (the BLL)
var peteTestBllHdl = autoMocker.ClassUnderTest;
// stub out call to DAL inside of BLL
autoMocker.Get<IPeteTestDAL>().Stub(c => c.GetStaffListAndRolesByTeam("4146")).Return(stubData);
// make call to BLL this should return stubData
List<StaffRoleByTeamCV> answer = peteTestBllHdl.GetStaffListAndRolesByTeam("4146");
// do simple asserts to test stubData present
// this passes
Assert.IsTrue(1 == answer.Count, "Did not find any rows");
// this fails
Assert.IsTrue(answer[0].Role == "boo", "boo was not found");
}
I tried using MockMode.AAA but still no joy

An new version of AutoMocker (1.0.3) is available. The new version supports relay mode as in this example..
[TestMethod]
public void ShouldSupportOrderedTest()
{
//Arrange
var autoMocker = new RhinoAutoMocker<CustomerUpdater>();
var mockRepository = autoMocker.Repository;
using (mockRepository.Ordered())
{
autoMocker.Get<ICustomerDataProvider>().Expect(x => x.GetCustomer(Arg<int>.Is.Anything)).Return(new CustomerItem());
autoMocker.Get<ICustomerDataProvider>().Expect(x => x.UpdateCustomer(Arg<CustomerItem>.Is.Anything));
autoMocker.Get<ILogWriter>().Expect(x => x.Write(Arg<string>.Is.Anything));
autoMocker.Get<ILogWriter>().Expect(x => x.Write(Arg<string>.Is.Anything));
autoMocker.Get<IMailSender>().Expect(x => x.SendMail(Arg<string>.Is.Anything, Arg<string>.Is.Anything));
}
//Act
autoMocker.ClassUnderTest.UpdateCustomerName(1, "Frank", "frank#somecompany.com");
//Assert
ExceptionAssert.Throws<ExpectationViolationException>(mockRepository.VerifyAll,"IMailSender.SendMail(anything, anything); Expected #1, Actual #0.\r\nILogWriter.Write(anything); Expected #1, Actual #0.\r\n");
}

I haven't tried, but this article suggests that by default all the mocks created by automocker are not replayed:
http://www.lostechies.com/blogs/joshuaflanagan/archive/2008/09/25/arrange-act-assert-with-structuremap-rhinoautomocker.aspx

Yes that was true for the previous version. But was changed to support ordered tests in version 1.0.3.

Related

How to unit test azure function using Xunit and Moq

I am very new to unit tests and recently started learning it from various online resources.
But still it confuses me when I need to implement it in my code.
For the given image which I have attached here, could anyone of you suggest me how should I start or where to start?
This is Azure function which I will be creating unit test for, framework/library I would prefer is Xunit and moq.
As mentioned in a comment, a good place to start when unit testing is looking at your code and identifying the different "paths" it can take and what the result of that path will be.
if (inventoryRequest != null)
{
// path 1
await _inventoryService.ProcessRequest(inventoryRequest);
_logger.LogInformation("HBSI Inventory Queue trigger function processed.");
}
else
{
// path 2
_logger.LogInformation("Unable to process HBSI Rate plan Queue.");
}
In your code, because of your if statement, there are 2 possible paths which will end in 2 different results = 2 unit tests.
Now you can start creating your unit tests but first you need to find out what you need to set up to be able to trigger your code.
private readonly ILogger _logger;
private readonly IInventoryService _inventoryService;
public InventoryServiceBusFunction(ILogger logger, IInventoryService inventoryService)
{
_logger = logger;
_inventoryService = inventoryService;
}
You have some dependencies being passed into your constructor with interfaces - great, this means we can mock them. We want to mock dependencies in unit tests because we want to control their behaviour for the tests. Also, mocking the dependencies negates any "real" behaviour the dependency might be performing i.e. database operations, API calls etc.
Using Moq we can mock the objects like so:
public class InventoryServiceBusFunctionTests
{
private readonly Mock<ILogger> _mockLogger = new Mock<ILogger>();
private readonly Mock<IInventoryService> _mockInventoryService = new Mock<IInventoryService>();
...
We will use these mocks later to make verifications on behaviour we expect to happen.
Next, we need to create an instance of the actual class we want to test.
// using a constructor in the test class will run this code before each test
public InventoryServiceBusFunctionTests()
{
// pass the mocked objects to initialize class
_inventoryServiceBusFunction = new InventoryServiceBusFunction(_mockLogger.Object, _mockInventoryService.Object);
}
Now that we have an instance of the InventoryServiceBusFunction class, we can use any of the public properties/methods in our tests.
[Fact]
public async Task GivenInventoryRequest_WhenFunctionRuns_ThenInventoryServiceProcessesRequest()
{
Now, remembering the paths from earlier, we can start to create the test cases. We can take the first path and create a [Fact] for it. You want to give your test case a meaningful name. I usually use the style of Given_When_Then to describe what is expected to happen.
Next, I usually add 3 comment sections to my test case:
// arrange
// act
// assert
This allows me to clearly see which parts of the test are doing what.
// act
await _inventoryServiceBusFunction.Run(inventoryRequest);
Next, I would fill in the \\ act section because this will tell me (via Intellisense) what I need to arrange. e.g. above, when hovering my mouse over the Run method, I can see that I need to pass an instance of InventoryRequest.
// arrange
var inventoryRequest = new InventoryRequest
{
Name = "abc123",
Quantity = 2,
Tags = new List<string>
{
"foo"
}
};
In the \\ arrange section, initialize an instance of the InventoryRequest class and set the properties. This can be any data as we aren't really interested in the data itself but more what happens when the code runs.
if (inventoryRequest != null)
{
// path 1
await _inventoryService.ProcessRequest(inventoryRequest);
_logger.LogInformation("HBSI Inventory Queue trigger function processed.");
}
Lastly, the \\ assert section. Here, we want to make assertions on what we expect to happen given the set up of the test. So given the InventoryRequest is not null, we expect the if to evaluate to true and we expect the _inventoryService.ProcessRequest(inventoryRequest) method to be executed.
// assert
_mockInventoryService
.Verify(x => x.ProcessRequest(It.Is<InventoryRequest>(ir => ir.Name == inventoryRequest.Name
&& ir.Quantity == inventoryRequest.Quantity
&& ir.Tags.Contains(inventoryRequest.Tags[0]))));
In Moq, we can use the .Verify() method on the mock object to assert that the method was called. We can use the It.Is<T> syntax to make assertions on the data that is passed to the method.
Here is the full test case for path 1:
[Fact]
public async Task GivenInventoryRequest_WhenFunctionRuns_ThenInventoryServiceProcessesRequest()
{
// arrange
var inventoryRequest = new InventoryRequest
{
Name = "abc123",
Quantity = 2,
Tags = new List<string>
{
"foo"
}
};
// act
await _inventoryServiceBusFunction.Run(inventoryRequest);
// assert
_mockInventoryService
.Verify(x => x.ProcessRequest(It.Is<InventoryRequest>(ir => ir.Name == inventoryRequest.Name
&& ir.Quantity == inventoryRequest.Quantity
&& ir.Tags.Contains(inventoryRequest.Tags[0]))));
}
Then for path 2, you are setting up the test so that the else condition is executed.
[Fact]
public async Task GivenInventoryRequestIsNull_WhenFunctionRuns_ThenInventoryServiceDoesNotProcessRequest()
{
// arrange
InventoryRequest inventoryRequest = null;
// act
await _inventoryServiceBusFunction.Run(inventoryRequest);
// assert
_mockInventoryService
.Verify(x => x.ProcessRequest(It.IsAny<InventoryRequest>()), Times.Never);
}
Note - in the \\ assert here, I am asserting that the await _inventoryService.ProcessRequest(inventoryRequest) method is never called. This is because you want the test to fail in this scenario as the method should only be executed in the if condition. You may also choose to verify that the logger method is called with the correct message.

Build/Test verification for missing implementations of query/commands in MediatR

We're using MediatR heavily in our LoB application, where we use the command & query pattern.
Often, to continue in development, we make the commands and the queries first, since they are simple POCOs.
This sometimes can lead to forgetting to create an actual command handler/query handler. Since there's no compile-time validation if there is actually an implementation for the query/command, I was wondering what would be the best approach to see if there's an implementation and throw an error if not, before being able to merge into master.
My idea so far:
Create a two tests, one for queries and one for commands, that scan all the assemblies for an implementation of IRequest<TResponse>, and then scan the assemblies for an associated implementation of IRequestHandler<TRequest, TResponse>
But this would make it still required to first execute the tests (which is happening in the build pipeline), which still depends on the developer manually executing the tests (or configuring VS to do so after compile).
I don't know if there's a compile-time solution for this, and even if that would be a good idea?
We've gone with a test (and thus build-time) verification;
Sharing the code here for the actual test, which we have once per domain project.
The mediator modules contain our query/command(handler) registrations, the infrastructure modules contain our handlers of queries;
public class MissingHandlersTests
{
[Fact]
public void Missing_Handlers()
{
List<Assembly> assemblies = new List<Assembly>();
assemblies.Add(typeof(MediatorModules).Assembly);
assemblies.Add(typeof(InfrastructureModule).Assembly);
var missingTypes = MissingHandlersHelpers.FindUnmatchedRequests(assemblies);
Assert.Empty(missingTypes);
}
}
The helper class;
public class MissingHandlersHelpers
{
public static IEnumerable<Type> FindUnmatchedRequests(List<Assembly> assemblies)
{
var requests = assemblies.SelectMany(x => x.GetTypes())
.Where(t => t.IsClass && t.IsClosedTypeOf(typeof(IRequest<>)))
.ToList();
var handlerInterfaces = assemblies.SelectMany(x => x.GetTypes())
.Where(t => t.IsClass && (t.IsClosedTypeOf(typeof(IRequestHandler<>)) || t.IsClosedTypeOf(typeof(IRequestHandler<,>))))
.SelectMany(t => t.GetInterfaces())
.ToList();
List<Type> missingRegistrations = new List<Type>();
foreach(var request in requests)
{
var args = request.GetInterfaces().Single(i => i.IsClosedTypeOf(typeof(IRequest<>)) && i.GetGenericArguments().Any() && !i.IsClosedTypeOf(typeof(ICacheableRequest<>))).GetGenericArguments().First();
var handler = typeof(IRequestHandler<,>).MakeGenericType(request, args);
if (handler == null || !handlerInterfaces.Any(x => x == handler))
missingRegistrations.Add(handler);
}
return missingRegistrations;
}
}
If you are using .Net Core you could the Microsoft.AspNetCore.TestHost to create an endpoint your tests could hit. Sort of works like this:
var builder = WebHost.CreateDefaultBuilder()
.UseStartup<TStartup>()
.UseEnvironment(EnvironmentName.Development)
.ConfigureTestServices(
services =>
{
services.AddTransient((a) => this.SomeMockService.Object);
});
this.Server = new TestServer(builder);
this.Services = this.Server.Host.Services;
this.Client = this.Server.CreateClient();
this.Client.BaseAddress = new Uri("http://localhost");
So we mock any http calls (or any other stuff we want) but the real startup gets called.
And our tests would be like this:
public SomeControllerTests(TestServerFixture<Startup> testServerFixture)
: base(testServerFixture)
{
}
[Fact]
public async Task SomeController_Returns_Titles_OK()
{
var response = await this.GetAsync("/somedata/titles");
response.StatusCode.Should().Be(HttpStatusCode.OK);
var responseAsString = await response.Content.ReadAsStringAsync();
var actualResponse = Newtonsoft.Json.JsonConvert.DeserializeObject<IEnumerable<string>>(responseAsString);
actualResponse.Should().NotBeNullOrEmpty();
actualResponse.Should().HaveCount(20);
}
So when this test runs, if you have not registered your handler(s) it will fail! We use this to assert what we need (db records added, response what we expect etc) but it is a nice side effect that forgetting to register your handler gets caught at the test stage!
https://fullstackmark.com/post/20/painless-integration-testing-with-aspnet-core-web-api

Checking exceptions with TestCaseData parameters

I'm using NUnit 3 TestCaseData objects to feed test data to tests and Fluent Assertions library to check exceptions thrown.
Typically my TestCaseData object contains two parameters param1 and param2 used to create an instance of some object within the test and upon which I then invoke methods that should/should not throw exceptions, like this:
var subject = new Subject(param1, param2);
subject.Invoking(s => s.Add()).Should().NotThrow();
or
var subject = new Subject(param1, param2);
subject.Invoking(s => s.Add()).Should().Throw<ApplicationException>();
Is there a way to pass NotThrow() and Throw<ApplicationException>() parts as specific conditions in a third parameter in TestCaseData object to be used in the test? Basically I want to parameterize the test's expected result (it may be an exception of some type or no exception at all).
[TestCaseData] is meant for Test Case Data, not for assertions methods.
I would keep the NotThrow and Throw in separate tests to maintain readability.
If they share a lot of setup-logic, I would extract that into shared methods to reduce the size of the test method bodies.
TestCaseData accepts compile time values, whereas TestCaseSource generates them on runtime, which would be necessary to use Throw and NotThrow.
Here's a way to do it by misusing TestCaseSource.
The result is an unreadable test method, so please don't use this anywhere.
Anyway here goes:
[TestFixture]
public class ActionTests
{
private static IEnumerable<TestCaseData> ActionTestCaseData
{
get
{
yield return new TestCaseData((Action)(() => throw new Exception()), (Action<Action>)(act => act.Should().Throw<Exception>()));
yield return new TestCaseData((Action)(() => {}), (Action<Action>)(act => act.Should().NotThrow()));
}
}
[Test]
[TestCaseSource(typeof(ActionTests), nameof(ActionTestCaseData))]
public void Calculate_Success(Action act, Action<Action> assert)
{
assert(act);
}
}
I ended up using this:
using ExceptionResult = Action<System.Func<UserDetail>>;
[Test]
[TestCaseSource(typeof(UserEndpointTests), nameof(AddUserTestCases))]
public void User_Add(string creatorUsername, Role role, ExceptionResult result)
{
var endpoint = new UserEndpoint(creatorUsername);
var person = GeneratePerson();
var request = GenerateCreateUserRequest(person, role);
// Assertion comes here
result(endpoint.Invoking(e => e.Add(request)));
}
private static IEnumerable AddUserTestCases
{
get
{
yield return new TestCaseData(TestUserEmail, Role.User, new ExceptionResult(x => x.Should().Throw<ApplicationException>())
.SetName("{m} (Regular User => Regular User)")
.SetDescription("User with Regular User role cannot add any users.");
yield return new TestCaseData(TestAdminEmail, Role.Admin, new ExceptionResult(x => x.Should().NotThrow())
)
.SetName("{m} (Admin => Admin)")
.SetDescription("User with Admin role adds another user with Admin role.");
}
}
No big issues with readability, besides, SetName() and SetDescription() methods in the test case source help with that.

Get exception when stubbing a property

When I run the following test:
[TestMethod]
public void MyTest()
{
var wizardCatalog = MockRepository.GenerateStub<IWizardCatalog>();
var firstQuestion = MockRepository.GenerateStub<IWizardQuestion>();
wizardCatalog.Stub(i => i.GetFirstQuestion()).Return(firstQuestion);
var choices = new List<IWizardChoice>();
firstQuestion.Stub(i => i.Choices).Return(choices);
}
I get 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;
Everything I read tells me that this stub operation is valid:
var choices = new List<IWizardChoice>();
firstQuestion.Stub(i => i.Choices).Return(choices);
What is going on?
PropertyBehaviour is on by default on stubs, but not on mocks. So you can either continue using a stub and change to the syntax suggested in the exception, or create a mock with GenerateMock<IWizardQuestion>() and use your existing .Stub(...).Return(...) syntax.

RhinoMocks AAA Syntax

I've spent a good part of the day trying to figure out why a simple RhinoMocks test doesn't return the value I'm setting in the return. I'm sure that I'm just missing something really simple but I can't figure it out. Here's my test:
[TestMethod]
public void CopyvRAFiles_ShouldCallCopyvRAFiles_ShouldReturnTrue2()
{
FileInfo fi = new FileInfo(#"c:\Myprogram.txt");
FileInfo[] myFileInfo = new FileInfo[2];
myFileInfo[0] = fi;
myFileInfo[1] = fi;
var mockSystemIO = MockRepository.GenerateMock<ISystemIO>();
mockSystemIO.Stub(x => x.GetFilesForCopy("c:")).Return(myFileInfo);
mockSystemIO.Expect(y => y.FileCopyDateCheck(#"c:\Myprogram.txt", #"c:\Myprogram.txt")).Return("Test");
CopyFiles copy = new CopyFiles(mockSystemIO);
List<string> retValue = copy.CopyvRAFiles("c:", "c:", new AdminWindowViewModel(vRASharedData));
mockSystemIO.VerifyAllExpectations();
}
I have an interface for my SystemIO class I'm passing in a mock for that to my CopyFiles class. I'm setting an expectation on my FileCopyDatCheck method and saying that it should Return("Test"). When I step through the code, it returns a null insteaed. Any ideas what I'm missing here?
Here's my CopyFiles class Method:
public List<string> CopyvRAFiles(string currentDirectoryPath, string destPath, AdminWindowViewModel adminWindowViewModel)
{
string fileCopied;
List<string> filesCopied = new List<string>();
try
{
sysIO.CreateDirectoryIfNotExist(destPath);
FileInfo[] files = sysIO.GetFilesForCopy(currentDirectoryPath);
if (files != null)
{
foreach (FileInfo file in files)
{
fileCopied = sysIO.FileCopyDateCheck(file.FullName, destPath + file.Name);
filesCopied.Add(fileCopied);
}
}
//adminWindowViewModel.CheckFilesThatRequireSystemUpdate(filesCopied);
return filesCopied;
}
catch (Exception ex)
{
ExceptionPolicy.HandleException(ex, "vRAClientPolicy");
Console.WriteLine("{0} Exception caught.", ex);
ShowErrorMessageDialog(ex);
return null;
}
}
I would think that "fileCopied" would have the Return value set by the Expect. The GetFilesForCopy returns the two files in myFileInfo. Please Help. :)
thanks in advance!
A mock will not start returning recorded answers until it is switched to replay mode with Replay(). Stubs and mocks do no work in the same way. I have written a blog post about the difference.
Also note that you are mixing the old record-replay-verify syntax with the new arrange-act-assert syntax. With AAA, you should not use mocks and Expect. Instead, use stubs and AssertWasCalled like this:
[TestMethod]
public void CopyvRAFiles_ShouldCallCopyvRAFiles_ShouldReturnTrue2()
{
// arrange
FileInfo fi = new FileInfo(#"c:\Myprogram.txt");
FileInfo[] myFileInfo = new FileInfo[2];
myFileInfo[0] = fi;
myFileInfo[1] = fi;
var stubSystemIO = MockRepository.GenerateStub<ISystemIO>();
stubSystemIO.Stub(
x => x.GetFilesForCopy(Arg<string>.Is.Anything)).Return(myFileInfo);
stubSystemIO.Stub(
y => y.FileCopyDateCheck(
Arg<string>.Is.Anything, Arg<string>.Is.Anything)).Return("Test");
CopyFiles copy = new CopyFiles(mockSystemIO);
// act
List<string> retValue = copy.CopyvRAFiles(
"c:", "c:", new AdminWindowViewModel(vRASharedData));
// make assertions here about return values, state of objects, stub usage
stubSystemIO.AssertWasCalled(
y => y.FileCopyDateCheck(#"c:\Myprogram.txt", #"c:\Myprogram.txt"));
}
Note how setting up the behavior of stubs at the start is separate from the assertions at the end. Stub does not set any expectations.
The advantage of seperating behavior and assertions is that you can make less assertions per test, making it easier to diagnose why a test failed.
Does the method FileCopyDateCheck really get called with the exact strings #"c:\Myprogram.txt" and #"c:\Myprogram.txt" as arguments?
I am not sure if FileInfo is doing something with c:\. Maybe it is modified to upper case C:\, which would make your expectation not working.
Maybe try an expectation which does not check for the exact argument values
mockSystemIO.Expect(y => y.FileCopyDateCheck(Arg<string>.Is.Anything, Arg<string>.Is.Anything)).Return("Test");
For more details about argument constraints see: Rhino Mocks 3.5, Argument Constraints
I am pretty sure that there are also possibilities to make the expectation case insensitive.
I think it's because your CopyvRAFiles() method isn't virtual.