I need to test my subscriber which is using MassTransit.
Below is a sample code :
using System;
using MassTransit;
public class AnimalSubscriber : Consumes<Animal>.Context
{
public void Consume(IConsumeContext<Animal> message)
{
//.. my code here..
}
}
Right now I have not Idea how to test the Subscriber. If someone could let me know some details; that would be very helpful!
As of now, foolishly I thought of creating a Object of AnimalSubscriber and call the Consume method.
[TestFixture]
public class Test
{
[Test]
public void SearchAnimals()
{
AnimalSubscriber subscriber = new AnimalSubscriber();
Animal request = new Animal
{
Id : 1,
Name : "Tiger"
};
//Not sure how to mock this IReceiveContext.
IReceiveContext context = new ReceiveContext();
IConsumeContext<Animal> message =new ConsumeContext<Animal>(context, request);
subscriber.Consume(null);
}
}
But I got stuck with the below line of code :
IConsumeContext<Animal> message =new ConsumeContext<Animal>(context, request); //<- Not sure how to mock this IReceiveContext.
Error : The type 'MassTransit.Context.ReceiveContext' has no
constructors defined
Need some advice please!
If you are using MassTransit v2 (which based on the interfaces you've specified above is indeed the case), you can use the Testing namespace to build out your tests.
An example unit test is available in the v2 repository branch: https://github.com/MassTransit/MassTransit/blob/v2-master/src/MassTransit.Tests/Testing/ConsumerTest_Specs.cs#L19
As an example, a testing fixture can be setup to build your consumer and send messages to it:
_test = TestFactory.ForConsumer<AnimalSubscriber>()
.InSingleBusScenario()
.New(x =>
{
x.ConstructUsing(() => new AnimalSubscriber());
x.Send(new Animal(), (scenario, context) => context.SendResponseTo(scenario.Bus));
});
_test.Execute();
Then you can build assertions around that test, such as:
_test.Sent.Any<A>().ShouldBeTrue();
Note that this only works with v2, the Testing namespace, while present in v3, doesn't exactly work yet (it didn't survive the move to async and I haven't taken the time to get it entirely working yet).
Related
I am running Unit Tests for my Xamarin.Forms application, and the Unit Tests throw Xamarin.Essentials.NotImplementedInReferenceAssemblyException:
I have created a Unit Test project for the app (using NUnit 3.12.0) and have written the below code to test the functionality.
[TestFixture()]
public class Test
{
[Test()]
public void TestCase()
{
AutoResetEvent autoEvent = new AutoResetEvent(true);
SomeClass someClass = new SomeClass();
someClass.SomeFunction((response) =>
{
Assert.AreEqual(response, "Hello")
autoEvent.Set();
});
autoEvent.WaitOne(); //** Xamarin.Essentials.NotImplementedInReferenceAssemblyException thrown here**
}
}
Below is the code under test from the Xamarin.Forms app:
public class SomeClass
{
public void SomeFunction(Action<string> callback)
{
// asynchronous code...
callback("Hello");
}
}
The above functionality works fine in the Xamarin.Forms app.
Note: I read that await/async can be used, however, I will have to make changes in the entire project. This is not a feasible solution for now.
Edit 1:
I have created a sample Xamarin.Forms project with Unit Tests in it. The project is available here
You need to add the Xamarin.Essentials NuGet Package to your Unit Test Project.
I highly recommend using Dependency Injection + Xamarin.Essentials.Interfaces, because certain Xamarin.Essentials APIs aren't implemented on .NET Core and you'll need to create your own implementation.
For example, here are some of the Xamarin.Essentials APIs I implemented in .NET Core for Unit Testing my GitTrends app:
AppInfo
Browser
DeviceInfo
Email
FileSystem
Launcher
MainThread
Preferences
SecureStorage
VersionTracking
While you have stated that the subject function cannot be made async at this time, the test however can be made async.
TaskCompletionSource can be used to wait for the callback to be invoked.
[TestFixture()]
public class Test {
[Test()]
public async Task TestCase() {
//Arrange
TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
Action<string> callback = (arg) => {
tcs.TrySetResult(arg);
};
SomeClass someClass = new SomeClass();
//Act
someClass.SomeFunction(callback);
string response = await tcs.Task;
//Assert
Assert.AreEqual(response, "Hello")
}
}
The issue can be related to what exactly the call back is trying to do. For example the Connectivity function of Xamarin.Essentials won't work (and will throw that type of exception) if you are calling it from your unit test as it is not running on a mobile platform and thus doesn't have that feature implemented.
A solution to this, at least one I've done for that type of functionality, is to create an interface. So, to continue with the example above regarding the Connectivity feature we can do this:
Make an interface
public interface IConnectivityService {
bool CanConnect()
}
Define both an actual implementation of it that will be used during the app running, and one for testing purposes
public ConnectivityService : IConnectivityService {
//implement the method
}
public ConnectivtyServiceMock : IConnectivityService {
//implement the method, but this is a mock, so it can be very skinny
}
Update your View/VM to accept this interface, and inside of the test case instantiate the mock version of it and pass that in.
In such scenarios where we have to reference device specific implementations from a unit test, we have to abstract it away in an interface and use that implementation instead
I checked your code and it is not throwing any Xamarin.Essentials exception. To run the unit test, I had to add the "NUnit3TestAdapter" nuget package.
You will have to wait for callback otherwise test will crash. You can use TaskCompletionSource suggested by #Nkosi.
[Test()]
public async Task TestCase()
{
XamarinMock.Init();
WebApi webApi = new WebApi();
TaskCompletionSource<HttpResponseMessage> tcs = new TaskCompletionSource<HttpResponseMessage>();
Action<HttpResponseMessage> callback = (arg) => {
tcs.TrySetResult(arg);
};
webApi.Execute(callback);
var response = await tcs.Task;
Console.WriteLine(response);
Assert.AreEqual(response.StatusCode, HttpStatusCode.OK);
}
How do I execute an automated test with the option of specifying it as a unit test or "light-weight integration test" without writing the same test twice and only changing the interface it depends on to make it either of the two?
Specifically, I want to execute one test and specify it as a unit test or an integration test.
Based on the mode I select, the test should generate a service interface.
I do not want to maintain two sets of identical code with the only difference being an interface:
Service for accessing external system (integration test)
MockService (unit test)
Example:
Construct testable business layer logic
It doesn't make sense to have a morphic test.
A unit test tests that a single piece of code works in isolation.
An integration tests tests that your code works when integrated into a larger codebase.
For instance, acceptance criteria and psuedocode for unit testing a viewmodel:
public TestMeViewModelTests {
public when_adding_a_warehouse_then_should_call_service_AddNewWarehouse_given_WarehouseModel {
//Arrange
var warehouseViewModel = new WarehouseViewModel { id=1 };
var service = new Mock<IService>();
var interfaceViewModel = new TestMeViewModel(service.Object);
//Act
interfaceViewModel.AddWarehouseCommand(warehouseViewModel);
//Assert
service.Verify(s=>s.AddNewWarehouse(wareHouseViewModel), Times.Once);
}
}
See, there's no cross-pollination of concerns. You're just testing that an idempotent operation is called when adding a new warehouse. If you were using an ORM, then you'd also have unit tests verifying that the dataservice calls are occurring.
If you were going to do an integration test, then your test project would be pointed to a "WarehouseTest" connectionstring that mirrors production, and your integration test might do that same logic, but then check to make sure that the warehouse that is inserted by the test is actually in your DB at the end of the test.
Okay, I think I understand what's happening now.
You want to be able to change the implementation used of an interface at runtime in order to change the location the unit tests run against.
In that case, you want some kind of abstract factory pattern.
Example:
public class ViewModel {
IService _service;
public ViewModel(IServiceFactory factory){
_service = factory.Create();
}
public void SaveWarehouse(Warehouse aWarehouse) {
_service.AddWarehouse(aWarehouse);
}
}
public interface IServiceFactory {
IService Create();
}
public class ProductionFactory : IServiceFactory { //Dependency injected
public IService Create() {
return new ProdService();
}
}
Unit Test:
public class ViewModelTest {
public void when_adding_warehouse() {
//Arrange
var aWarehouse = new WarehouseViewModel { id=1 };
var serviceFactory = new Mock<IServiceFactory>().Object);
var service = new Mock<IService>();
serviceFactory.Setup(factory => factory.Create()).Returns(service.Object);
var viewModel = new ViewModel(serviceFactory.Object);
//Act
viewModel.AddWarehouseCommand(warehouseViewModel);
//Assert
service.Verify(s=>s.AddNewWarehouse(aWarehouse), Times.Once);
}
}
Integration Test:
Your integration test will include a local internal IService implementation and a local internal IServiceFactory implementation returning the local IService implementation. All of your tests will run perfectly fine and you can control where the data goes to very easily.
Add an entry to the app config.
App Config:
<appSettings>
<add key="IsUnitTest" value="True" />
</appSettings>
Then get the key/value pair from the config file and set your service dependency based on the config value.
Test
[TestClass]
public class MyTest
{
IServices _service = null;
[TestInitialize]
public void Setup()
{
var isUnitTest = bool.Parse(ConfigurationManager.AppSettings["IsUnitTest"]);
if (isUnitTest)
{
_service = new MockService();
}
else
{
_service = new Service();
}
}
.
.
.
I disagree C Bauer. No consensus here at all. Mocks and dependency injection go a long way to solving this problem. I've seen this approach used more frequently over the last couple of years and it works fine.
Usually in Agile environments where roles are cross functional. Some teams want a single code base/solution to work from. Especially where the size of the code base is relatively small, having "unit" tests able to function as light weight Integration tests works fine. There is no black and white solution here, only the one that works best for the problem at hand. Regardless of what others say there are multiple ways to approach this problem and the solutions/approaches are growing and changing all the time.
I'm a beginner at writing unit tests and I have a test I'm trying to get working. I'll start of by explaining what I'm trying to test.
I'm trying to test a method which saves messages in a Mvc 4 project. The method is called SaveMessage and is shown below.
namespace ChatProj.Service_Layer
{
public class UserService : IUserService
{
public MessageContext messageContext = new MessageContext();
public UserService()
{
_messageRepository = new MessageRepository(messageContext);
}
private IMessageRepository _messageRepository;
-> public void SaveMessage(Message message)
{
messageContext.Messages.Add(message);
_messageRepository.Save();
}
The _messageRepository.Save in the SaveMessage method is implemented in my DAL layer MessageRepository and looks like this:
public void Save()
{
context.SaveChanges();
}
This way of saving will seem a bit overcomplicated, but I structured the project this way because I didn't want the service layer (IUserService & UserService) to handle operations that could & should (i think) be handled by the Data Access Layer (IMessageRepository & MessageRepository).
Now comes the tricky part. I've been trying to understand how I could unit test this. This is my try:
namespace ChatProj.Tests
{
[TestFixture]
class MessageRepositoryTests
{
[SetUp]
public void Setup()
{
}
[Test]
public void SaveMessage_SaveWorking_VerifyUse()
{
//Arrange
var userServiceMock = new Mock<UserService>();
var message = new Message { MessageID = 0, Name = "Erland", MessageString = "Nunit Test", MessageDate = DateTime.Now };
var repositoryMock = new Mock<IMessageRepository>();
var contextMock = new Mock<MessageContext>();
MessageRepository messageRepository = new MessageRepository(contextMock.Object);
UserService userService = new UserService();
//Act
userService.SaveMessage(message);
//Assert
repositoryMock.Verify(m => m.Save());
userServiceMock.Verify(m => m.SaveMessage(message));
}
}
I get this error: Imgur link , and I'm not quite sure how to solve it. I've tried looking at several other SO posts but I fail to make the test work.
So I'm wondering, how do I practically get my Unit Test to work?
You should setup your MessageContext properties to return fake data and don't make real Db call with SaveChanges method.
Right now it still tries to access a real DB.
But you can setup only virtual properties or if it will be an inteface.
So the best solution is to extract an interface from your MessageContext and inject it into repository. Then you can easily mock your IMessageContext interface and force it to return appropriate in-memory data.
Take a look at these two lines:
UserService userService = new UserService();
//Act
userService.SaveMessage(message);
You're creating a userService instance, and then immediately saving your message. Now jump into the SaveMessage code.
public void SaveMessage(Message message)
{
messageContext.Messages.Add(message);
_messageRepository.Save();
}
Ok, now you're adding stuff to messageContext, and then calling _messageRepository.Save(). But where are messageContext and _messageRepository instantiated?
public MessageContext messageContext = new MessageContext();
public UserService()
{
_messageRepository = new MessageRepository(messageContext);
}
You're creating them at instantiation. The mocks that you've created in your test aren't being used. Instead of creating instances of these objects in the constructor, you might consider passing them into the UserService constructor as arguments. Then, you can pass in mocked instances in your test.
I'm practicing on writing unit tests for the first time, and I have some questions. I'll start of by explaining what I'm trying to test.
I would like to test a method which looks like this:
public bool IsAdmin(HubCallerContext hubCallerContext)
{
return hubCallerContext.User.IsInRole("admin");
}
The method is implemented in a class UserService, which is connected to a interface IUserService.
I'm trying to create 2 tests:
One with a HubCallerContext which is in the role of "admin" and will assert true.
One with a HubCallerContext which is in the role of "user" and will assert false.
I've created a new class library in my solution, where I've refrenced the project I'm testing. I've installed NUnit and Moq, and created a test class which looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ChatProj;
using NUnit.Framework;
using ChatProj.Controllers;
using Moq;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using ChatProj.DAL;
using ChatProj.Service_Layer;
using System.Threading.Tasks;
namespace ChatProj.Tests
{
[TestFixture]
public class Class1
{
[SetUp]
public void Setup()
{
}
[Test]
public void IsAdmin_CalledByAdmin_ReturnTrue()
{
UserService userService = new UserService();
bool result = userService.IsAdmin( ? );
Assert.IsTrue( result, "Something is wrong." );
}
[Test]
public void IsAdmin_CalledByUser_ReturnFalse()
{
UserService userService = new UserService();
bool result = userService.IsAdmin( ? );
Assert.IsFalse( result, "Something is wrong." );
}
}
}
Here I start to get confused. (I've marked the parameters of the IsAdmin calls with "?" because I'm not sure what to put there.)
I've read about mocks, stubs, fakes and dummies, but the definitions are to abstract for me to really grasp. I've found these definitions for example:
- Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.
- Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example).
- Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messages it 'sent'.
- Mocks are objects pre-programmed with expectations which form a specification of the calls they are expected to receive.
As I've designed my test class, I would need some sort of substitution for my HubCallerContext. This is assuming I'm testing the "IsAdmin" method the right way.
So my questions are:
Am I testing the "IsAdmin" method in a good way?
How would I practically make the tests work? Do I use a mock, and in that case, could you show how I would implement that, or point me in the right direction? Here is how the HubCallerContext works for
refrence.
Assuming HubCallerContext is this one - https://github.com/SignalR/SignalR/blob/master/src/Microsoft.AspNet.SignalR.Core/Hubs/HubCallerContext.cs - then setting up the tests will be easy. You just want two mocks of IPrincipal, one of which returns true for the .IsInRole("admin") call and the other that returns false.wrap these two in mocks of IRequest.
The syntax will vary depending on the mocking framework used, but your tests will end up something like:
[Test]
public void IsAdmin_CalledByAdmin_ReturnTrue()
{
UserService userService = new UserService();
var principalMock = new Mock<IPrincipal>();
principalMock.Setup(x => x.IsInRole("admin")).Returns(true);
var requestMock = new Mock<IRequest>();
requestMock.Setup(x => x.User).Returns(principalMock.Object);
var result = userService.IsAdmin(new HubCallerContext(requestMock.Object, ""));
Assert.IsTrue( result, "Something is wrong." );
}
[Test]
public void IsAdmin_CalledByUser_ReturnFalse()
{
UserService userService = new UserService();
var principalMock = new Mock<IPrincipal>();
principalMock.Setup(x => x.IsInRole("admin")).Returns(false);
var requestMock = new Mock<IRequest>();
requestMock.Setup(x => x.User).Returns(principalMock.Object);
var result = userService.IsAdmin(new HubCallerContext(requestMock.Object, ""));
Assert.IsFalse( result, "Something is wrong." );
}
I haven't checked if the above compiles, but it is based on the syntax needed for Moq.
I think that it would be much easier for You to write these two unit tests if You would change the method under test a little (assuming it's not a part of legacy code).
If you define the method this way:
public bool IsAdmin(IPrincipal user)
{
return user.IsInRole("admin");
}
things would get pretty simple (btw. check the "Law of Demeter" ;)). You can pass in a mock object (since the user parameter is an interface - IPrincipal) returning true if the user should be in role "admin" and false otherwise.
The benefit of this solution is that You don't have to build a graph of mock objects and the arrange part of your test is pretty simple. Your tests could look somewhat like this:
[Test]
public void IsAdmin_CalledByAdminUser_ReturnTrue()
{
//Arrange
var principalMock = new Mock<IPrincipal>();
principalMock.Setup(x => x.IsInRole("admin")).Returns(true);
//Act
var userService = ...// create an instance of userService here
var result = userService.IsAdmin(principalMock);
//Assert
Assert.IsTrue(result);
}
[Test]
public void IsAdmin_CalledByNonAdminUser_ReturnFalse()
{
//Arrange
var principalMock = new Mock<IPrincipal>();
principalMock.Setup(x => x.IsInRole("admin")).Returns(false);
//Act
var userService = ...// create an instance of userService here
var result = userService.IsAdmin(principalMock);
//Assert
Assert.IsFalse(result);
}
I would recommend You to read this series of blog posts (I think it's pretty cool :)): http://www.daedtech.com/tag/unit-testing
You can get the list of roles and check for each roles using foreach.
Given the following, is this the proper use of MOQ? I am very new to "mocking", "stubbing", "faking", etc. and just trying to wrap my head around it.
The way I understand it is that this mock is providing a known result, so when I test this service using it, the service reacts properly?
public interface IRepository<T> where T : class
{
void Add(T entity);
void Delete(T entity);
void Update(T entity);
IQueryable<T> Query();
}
public interface ICustomerService
{
void CreateCustomer(Customer customer);
Customer GetCustomerById(int id);
}
public class Customer
{
public int Id { get; set; }
}
public class CustomerService : ICustomerService
{
private readonly IRepository<Customer> customerRepository;
public CustomerService(IRepository<Customer> customerRepository)
{
this.customerRepository = customerRepository;
}
public Customer GetCustomerById(int id)
{
return customerRepository.Query().Single(x => x.Id == id);
}
public void CreateCustomer(Customer customer)
{
var existingCustomer = customerRepository.Query().SingleOrDefault(x => x.Id == customer.Id);
if (existingCustomer != null)
throw new InvalidOperationException("Customer with that Id already exists.");
customerRepository.Add(customer);
}
}
public class CustomerServiceTests
{
[Fact]
public void Test1()
{
//var repo = new MockCustomerRepository();
var repo = new Mock<IRepository<Customer>>();
repo.Setup(x => x.Query()).Returns(new List<Customer>() { new Customer() { Id = 1 }}.AsQueryable());
var service = new CustomerService(repo.Object);
Action a = () => service.CreateCustomer(new Customer() { Id = 1 });
a.ShouldThrow<InvalidOperationException>();
}
}
I am using xUnit, FluentAssertions and MOQ.
The way I understand it is that this mock is providing a known result,
so when I test this service using it, the service reacts properly?
This statement is correct - the unit test should be verifying that the class you're testing (in this case, CustomerService) is exhibiting the behavior you desire. It's not intended to verify that its dependencies are behaving as expected (in this case, IRepository<Customer>).
Your test is good* - you're setting up your mock for the IRepository and injecting into your SystemUnderTest, and verifying that the CustomerService.CreateCustomer() function is exhibiting the behavior that you expect.
*The overall setup of the test is fine, but I'm not familiar with xUnit, so the final two line's syntax is foreign to me, but it looks like it's correct based on the semantics. For reference, you would do the last two lines in NUnit like so:
Assert.Throws<InvalidOperationException>(() => service.CreateCustomer(...));
The test looks fine to me, the mock just provides a fake repository that returns a hardcoded answer just for the test, so the test only cares about the service you're testing and don't deals with a real-life database or whatever, since you're not testing it here.
I would only add one thing to the test to be even more complete. When you setup method calls on the mocks, make sure they were really called by the system under test. After all, the service is supposed to ask the repo for some object and throw only under a certain return value. Moq in particular provides a syntax for this:
repo.VerifyAll();
What this does is simply checking that the setups you've placed before were actually called at least once. This can protect you from errors where the service just throws the exception right away without calling the repo (easy to spot in examples like yours, but with complex code it's easy to miss a call). With that line, at the end of your test, if your service didn't called the repo asking for the list (and with that specific set of parameters), the test will fail too, even if the exception was properly thrown.