My team is just getting started with using MassTransit and we are trying to figure out how unit testing IConsumer implementations work. The MassTransit documentation is incomplete and all of the examples I have found so far use NUnit. We are trying to use XUnit with Moq to do our unit testing.
I know that we need to set up one instance of the MassTransit test harness, which in NUnit is done with a OneTimeSetup and to replicate that we should use IClassFixture in XUnit. I'm struggling with getting that to work with the test harness, though.
I have seen Chris Patterson's ConsumerTest_Specs.cs example on the MassTransit GitHub, but I'm having a hard time translating it to work in XUnit and Moq.
https://github.com/MassTransit/MassTransit/blob/master/src/MassTransit.Tests/Testing/ConsumerTest_Specs.cs
I'm trying to test a very simple consumer to start with. All it does is receive the message and then make a call to a repository. I want to write an XUnit test that mocks the repository and verifies that the repository method was called.
Does anyone have any examples of how to do something like this?
public class NewVMRequestRejectedConsumer : IConsumer<INewVMRequestRejected>
{
private readonly INewVMRequestRepository _newVMRequestRepository;
public NewVMRequestRejectedConsumer(INewVMRequestRepository newVMRequestRepository)
{
_newVMRequestRepository = newVMRequestRepository;
}
public Task Consume(ConsumeContext<INewVMRequestRejected> context)
{
_newVMRequestRepository.AddReasonForRejection(context.Message.RequestId, context.Message.Reason);
return Task.CompletedTask;
}
}
Since ConsumeContext<out T> and INewVMRequestRepository are interfaces there is no problem mocking them using moq, e.g.
//Arrange
var repository = new Mock<INewVMRequestRepository>();
var sut = new NewVMRequestRejectedConsumer(repository.Object);
//Act
sut.Consume(Mock.Of<ConsumeContext<INewVMRequestRejected>>(m =>
m.Message.RequestId == "id" && m.Message.Reason == "reason"));
//Assert
repository.Verify(m => m.AddReasonForRejection("id", "reason"), Times.Once);
Related
So I've been trying to write a test for mass transit using the in-memory feature. I wondered what peoples approach was to waiting for consumers to execute. In the example below a use a sleep or I've also tried a while loop, but not a fan of either, any better ideas? I basically want to check that the consumer is executed.
[Fact]
public async Task SomeTest()
{
var busControl = Bus.Factory.CreateUsingInMemory(cfg =>
{
cfg.ReceiveEndpoint("commands", ec =>
{
ec.LoadFrom(context);
});
});
var address = new Uri(bus.Address, "commands")
await sendEndpoint.Send(MyExampleCommand());
Thread.Sleep(2000);
//Check nsubstitute mock received
}
Look at the test harness features that are built into MassTransit. They should give you some good ideas of how to test them.
You can look at the harness tests to see how they should be used. Note that they work with any test framework, not just NUnit.
https://github.com/MassTransit/MassTransit/blob/develop/tests/MassTransit.Tests/Testing/ConsumerTest_Specs.cs
The Testing documentation explains how to use the test harnesses.
First attempt at any real unit testing. I have a WPF client application which receives data from methods in a WCF service. These method calls are made directly from my view models in the client app:
public string LoadArticle()
{
MyServiceClient msc = new MyServiceClient();
return Article = msc.GetArticle(_UserName);
}
I then have a test project where I new up a viewmodel then call my method:
[TestMethod]
public void LoadArticleTestValid()
{
var articleViewModel = new ArticleViewModel("Thomas");
string userName = "Thomas";
string expected = "Article 1";
var actual = articleViewModel.LoadArticle(userName);
etc.
}
Obviously this test will fail because the client application cannot reach the service to invoke LoadArticle. How is this situation tackled? Do I use Dependency Injection and pass a IMyService interface of some kind into the constructor instead of creating MyServiceClient in the ViewModel or do I mock the service somehow?
This is the problem:
MyServiceClient msc = new MyServiceClient();
This creates a tight coupling between ArticleViewModel and MyServiceClient. In order to unit test just ArticleViewModel this dependency would need to be mocked. If there's an IMyServiceClient then you'd supply that to the class:
public ArticleViewModel
{
private IMyServiceClient ServiceClient { get; set; }
public ArticleViewModel(IMyServiceClient serviceClient)
{
this.ServiceClient = serviceClient;
}
// etc.
}
Then code within that class wouldn't create a new service client, it would just use the one that's in that property.
Then in the unit test you'd create a mock of IMyServiceClient, define expected behaviors on that mock, and supply it to the object being tested. How you do that depends on the mocking library. A quick example in Rhino Mocks might look like this:
// arrange
var serviceClient = MockRepository.GenerateMock<IMyServiceClient>();
serviceClient.Stub(c => c.GetArticle(Arg<string>.Is.Anything)).Return("Article 1");
var model = new ArticleViewModel(serviceClient);
// act
var result = model.LoadArticle("Thomas");
// assert
Assert.AreEqual("Article 1", result);
The idea here is that the unit test is only testing the LoadArticle method, not the dependencies invoked by that method. Those dependencies are supplied with expected behaviors and the result is examined based on those expected behaviors.
Note: There's nothing stopping the unit test from supplying the actual implementation of MyServiceClient as well, instead of a mock. The unit test project just needs the configuration for that service to work. (Unit test projects are application hosts, they can have App.config files.) This would be an integration test rather than a unit test, but the same assertions of the results can be made.
Yes, I think you are right I would suggest a constructor parameter of IMyService, which you can use to inject a mock into the object for testing.
Further! I would suggest not using the autogenerated service client. if you copy and paste the code out into your own class you can make it implement IMyService and effectivly hide the fact that it uses WCF, goes direct to the DB or is a mocked object from the real code.
this will allow you to inject your Mock into the WPF for UI testing
I'm a bit confused with writing unit tests in C#. I've written the following class for learning Moq. I've noticed the [SetUp] is actually a reference from NUnit. How can I write a test class that only uses one framework or another or whether that's possible? If I want to use Moq what attributes am I missing to successfully run this test? I know there's [TestFixture], [TestMethod] etc.. but which one do I use for Moq!
Thanks,
James
public class CatalogCommandTests
{
private Mock<IReferenceData> _mockReferenceData;
[SetUp]
public void TestInitialize()
{
_mockReferenceData = new Mock<IReferenceData>();
}
public void TestMyGetMethodReturnsListOfStrings()
{
var contractsList = new List<Contract>();
_mockReferenceData.Setup(x => x.MyGetMethod()).Returns(contractsList);
}
}
Your mock looks good. To get the mock of IReferenceData you have to call _mockReferenceData.Object.
A method decorated with the SetUp Attribute will be executed before each test method is called.
(See: Setup).
If you want that TestMyGetMethodReturnsListOfStrings gets called you have to decorate the method with the Test attribute
(See: Test).
we have a WPF application that uses CurrentPrincipal to handle security. This all works fine.
Now, from within a test project, we call view model operations. The problem is, that in the initialization of the test we create a new instance of the application but we don't know how to set the CurrentPrincipal on this application:
private void TestInitialize()
{
var app = new App();
// setting Thread.CurrentPrincipal doesn't set app thread it seems
}
Anyone has an idea how to set the CurrentPrincipal for a WPF application from outside the application?
There are many different strategies to choose here, but one strategy which many adopt to is mocking the IPrincipal and IIdentity objects necessary to simulate principals and identities of the current thread. I will show how this can be done using the Mocking framework Moq next:
using System.Security.Principal;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace MockingIdentitySample.Test
{
[TestClass]
public class UnitTest1
{
[TestInitialize]
public void TestInitialize()
{
SetupMockedPrincipalAndIdentity(true, true, "John Doe");
}
private void SetupMockedPrincipalAndIdentity(bool autoSetPrincipal, bool isAuthenticated, string identityName)
{
var mockedPrincipal = new Mock<IPrincipal>();
var mockedIdentity = new Mock<IIdentity>();
mockedIdentity.Setup(m => m.Name).Returns(identityName);
mockedIdentity.Setup(m => m.IsAuthenticated).Returns(isAuthenticated);
mockedPrincipal.Setup(p => p.Identity).Returns(mockedIdentity.Object);
if (autoSetPrincipal)
Thread.CurrentPrincipal = mockedPrincipal.Object;
}
[TestMethod]
public void TestMethod1()
{
Assert.AreEqual(Thread.CurrentPrincipal.Identity.Name, "John Doe");
Assert.IsTrue(Thread.CurrentPrincipal.Identity.IsAuthenticated);
}
}
}
Note that Thread.CurrentPrincipal can be set directly, but using a mocking framework or isolation framework in general is strongly suggested when writing unit tests. Often we are testing not the security code but are writing unit tests for view models or similar classes in our code and therefore we abstract, isolate or mock these dependencies such as the current principal on the thread away so we can focus on what we really want to write unit tests for - the logic of our code.
Of course, one must choose if mocking is the right choice here or if Moq is the correct framework to use. There are several alternatives when it comes to mocking. Moq is really nice mocking framework, but cannot mock static methods for example. Other mocking frameworks offer more functionality than Moq and so on.
A quickstart for Moq is available here if this seems like a possible route to follow:
http://code.google.com/p/moq/wiki/QuickStart
(Please note, I am an independent developer and the reason I suggested Moq was not because of my liking, but because I have used this mocking framework earlier for similar scenarios as yours here).
Why won't this test method work? I keep getting requires a return value or an exception to throw.
public AuthenticateResponse Authenticate(string username, string password)
{
string response = GetResponse(GetUrl(username, password).ToString());
return ParseResponse(response);
}
[TestMethod()]
[ExpectedException(typeof(XmlException))]
public void Authenticate_BadXml_ReturnException()
{
MockRepository mockRepository = new MockRepository();
SSO sso = mockRepository.Stub<SSO>();
sso.Stub(t => t.GetResponse("")).Return("<test>d");
AuthenticateResponse response = sso.Authenticate("test", "test");
}
Your repository is still in "record" mode. You're mixing record/replay semantics (the "old" way of doing things) with the newer AAA (arrange/act/assert) style.
Instead of creating your own repository, simply use:
var sso = MockRepository.GeneateStub<SSO>();
Everything should work fine now.
Your last line is calling the Authenticate method on your stub object, you haven't set up a return or value or exception to throw when calling it, so Rhino Mocks doesn't know what the stub should do and it causes an error. You probably don't want to call a method on your stub - that seems kind of pointless to me, is there another object (that you're actually testing in this test) that you should be calling a method on?
Is that your whole test? If so, your test makes no sense. The only object in your test is the one you're stubbing--where is the subject of the test?
If you're trying to test the SSO class, you absolutely never want to mock/stub it. If SSO has one or more dependencies, use the mocking framework to set up canned interactions between those dependencies and your SUT. That is the exact purpose of a mocking framework.