What is NoOpMediator in Clean Architecture - mediatr

I am playing around with the Clean Architecture by Ardalis.
Can someone please explain what this NoOpMediator role in Unit testing?
using System.Runtime.CompilerServices;
using MediatR;
namespace Clean.Architecture.UnitTests;
public class NoOpMediator : IMediator
{
public Task Publish(object notification, CancellationToken cancellationToken = default)
{
return Task.CompletedTask;
}
...
...
}
It does not seem to do anything. For four of its methods it returns Task.CompletedTask. And for the rest of the two it returns Task.FromResult<object?>(default)
Further more in the BaseEfRepoTestFixture class here, there is no configuration of Mock object. Bit misty.
Also noted that this is configured in CustomWebApplicationFactory way down here.
services.AddScoped<IMediator, NoOpMediator>();
Even if I comment out that line, the tests still pass.
There should be an example test to show how this works.

Related

unable to mock crudrepository save method

#ExtendWith(MockitoExtension.class)
class taskTestMain {
#InjectMocks
task task1;
#Mock
private statusRepository statusRepo;
#Mock
status statusRec;
#Test
void test() {
Mockito.when(statusRepo.save(statusRec)).thenReturn(statusRec);
task1.method();
}
}
class task
{
method()
{
statusRec = statusRepo.save(statusRec); //after this step I get Potential stubbing exception
}}
I have tried several ways . I am not able to figure this out. Please suggest how to proceed. Below I have pasted the junit error. task- Strict stubbing argument mismatch. Please check:
this invocation of 'save' method:statusRepo.save(status#8bffb8b);
-> at task.run(task.java:80)
has following stubbing(s) with different arguments: 1. statusRepo.save(status#26a2f7f9
); -> at .taskTestMain.test(taskTestMain.java:110)
Typically, stubbing argument mismatch indicates user mistake when writing tests.
Mockito fails early so that you can debug potential problem easily.
Thanks for your time
To be honest I'am not totally sure about this but I have a guess.
Mockito.when(statusRepo.save(statusRec)).thenReturn(statusRec);
With this stub you simply want return the first parameter passed into the save Method? If this is true there is a more generic way to do this.
when(statusRepo.save(any(TcMdhTotemConsensusStatus.class))).then(returnsFirstArg());
This stub will always return the first argument that is passed into your save
method.
See this stackoverflow post for more information. There also some alternatives in case your Java or Mockito Version does not match.

Mvvmcross Testing different view models fails when running together

I've come across an interesting error. I have two test files for my xamarin mobile application, both testing view models:
public class TestFirstViewModel : MvxIoCSupportingTest
{
public void AdditionalSetup() {
//Register services and dependencies here.
}
[Fact]
public TestMethod1() {
// Successful test code here.
}
}
That's in one file. In another file, I have:
public class TestSecondViewModel : MvxIoCSupportingTest
{
public void AdditionalSetup() {
//Register services and dependencies here, slightly different from first
}
[Fact]
public TestMethod2() {
// Successful test code here.
}
}
When I run these files individually (I'm using xunit), they work just fine. However, when I run them together, I get the following error on one of the test cases:
Result Message: Cirrious.CrossCore.Exceptions.MvxException : You cannot create more than one instance of MvxSingleton
Result StackTrace:
at Cirrious.CrossCore.Core.MvxSingleton`1..ctor()
at Cirrious.CrossCore.IoC.MvxSimpleIoCContainer..ctor(IMvxIocOptions options)
at Cirrious.CrossCore.IoC.MvxSimpleIoCContainer.Initialize(IMvxIocOptions options)
at Cirrious.MvvmCross.Test.Core.MvxIoCSupportingTest.ClearAll()
at Cirrious.MvvmCross.Test.Core.MvxIoCSupportingTest.Setup()
at Project.Test.TestFirstViewModel.TestMethod1() in ...
Can anyone tell me what's going on here?
The issue stems from the parallelization of XUnit without the option to do proper tear-down. You could diable parallelization in the AssemblyIndo.cs file in you test project by adding:
[assembly: CollectionBehavior(DisableTestParallelization = true)]
I ended up solving this question by changing testing frameworks. I had different ioc singleton initializations, because, well, they're different test cases and needed different inputs/mocks. Instead of using Xunit, I resorted to Nunit where their cache clearing was much more defined: Xunit doesn't exactly believe in setup and tear-down, so it made a test environment like this more difficult.
I fixed the issue by using the collection attribute.
[Collection("ViewModels")]
class ViewModelATest : BaseViewModelTest {
...
}
[Collection("ViewModels")]
class ViewModelBTest : BaseViewModelTest {
...
}
The base view model test class has the mock dispatcher and performs the singleton registrations in the additional setup method.
Each of my tests calls ClearAll() at the beginning.
I hade some success with setup things in a constructor and add this check:
public PaymentRepositoryTests()
{
if (MvxSingletonCache.Instance == null)
{
Setup();
}
//other registerings.
}`
Also I did implement the IDisposable Interface
public void Dispose()
{
ClearAll();
}
But tbh not sure how much impact that had..
It works ok with xunit
Copy MvxIocSupportingTest and Mvxtest in your xunit PCL project.
Modify MvxTest to remove the attributes and use a simple contructor:
public class MvxTest : MvxIoCSupportingTest
{
protected MockMvxViewDispatcher MockDispatcher { get; private set; }
public MvxTest()
{
Setup();
}
...
And in each of you test, derive from IClassFixture
public class TestRadiosApi : IClassFixture<MvxTest>
{
[Fact]
public async Task TestToken()
{
...
xunit will create the MvxTest class only once for all tests.

How to priortized the test cases in maven run?

I have 3 test cases i.e. 1 2 3. How will i give priority as 2 1 3 while executing maven command.
I assume you want to do it because you need some prerequisition prior the test can be run. You can do it by #Before Annotation prior the actual testcase, or you can call other tests from the test method.
Say, testClient() test will test and verify that new client can be added to the system. Then you can do this:
#Test
public void testWithdrawal(){
testClient(); // i need client existing before the test can be run
// ... do something else
}
In that case you have assured that prerequisites are fullfilled and dont have to worry much about the testcases order
EDIT
I think I understand your needs, because I am in quite similar situation. How I solved it:
For create I have special class, which can create me a data and return needed data. So, i have something like:
#Test
public void testShare(){
CreateTests create = new CreateTests; //This will just initialize the object
create.testCreate(); // this method can contain steps needed to create
String justCreatedEntity = create.getEntity(); // just example how you can use the just created entity in further tests
}
And my class to solve the create is something like this
public class CreateTests{
private static String entity; //static because i dont want it to be flushed when test ends
public void testCreate() throws Exception{
WebDriverBackedSelenium selenium = new WebDriverBackedSelenium(driver, "baseURL");
selenium.... // All the selenium stuff
setEntity(selenium.getText("id=mainForm.createdentity"));
}
public void setEntity(String ent){
this.entity = ent;
}
public String getEntity(){
return entity;
}
Its just an outline - but basically, I have these "crucial" entities as standalone objects, called by the test class. Inside test, i verify everything throgh getters. Like:
Assert.assertNotNull(create.getAuctionID(),"New Entity is NULL!" );
You can run mvn test with options to specify a single test, or multiple tests. The order they are run in is the order specified on the command line.
Reference is here: http://maven.apache.org/plugins/maven-surefire-plugin/examples/single-test.html
Note that Java suggests that the good unit testing practice of tests not requiring to be run in order and test to not rely on each other:
http://java.sun.com/developer/Books/javaprogramming/ant/ant_chap04.pdf

Unit testing custom MembershipProvider.ValidateUser, using code in Global.asax

I have a unit test to check my AccountController.LogIn method. A redirect result is returned to indicate successs, otherwise a viewresult is returned.
The test always fails as the return type is always viewresult, even though the test should return success as the credentials are valid, however I can't identify where the problem is.
My TestMethod:
CustomerRepositoryTest.cs
[TestMethod]
public void Can_Login_With_Valid_Credentials()
{
// Arrange
Mock<IAddressRepository> mockAddressRepository = new Mock<IAddressRepository>();
Mock<ICustomerRepository> mockCustomerRepository = new Mock<ICustomerRepository>();
Mock<IOrderRepository> mockOrderRepository = new Mock<IOrderRepository>();
LoginViewModel model = new LoginViewModel
{
Email = "me#5.com",
Password = "password"
};
AccountController target = new AccountController(mockCustomerRepository.Object, mockAddressRepository.Object, mockOrderRepository.Object);
// Act
ActionResult result = target.LogIn(model);
// Assert
Assert.IsInstanceOfType(result, typeof(RedirectResult));
Assert.AreEqual("", ((RedirectResult)result).Url);
}
When I run the test, it fails in My AccountController Login method when I call ValidateUser
AccountController.cs
if (Membership.ValidateUser(LoginModel.Email, LoginModel.Password))
{
...
return RedirectToRoute(new
{
controller = "Account",
action = "Details"
});
}
else
{
return View();
}
My custom MembershipProvider ValidateUser looks like this:
AccountMembershipProvider.cs
public class AccountMembershipProvider : MembershipProvider
{
[Inject]
public ICustomerRepository repository { get; set; }
public override bool ValidateUser(string username, string password)
{
var cust = repository.GetAllCustomers().SingleOrDefault..
When I run the application normally i.e. not testing, the login works fine. In the application I inject the CustomerRepository into the custom membership provider in Global.asax:
public class MvcApplication : System.Web.HttpApplication
{
private IKernel _kernel = new StandardKernel(new MyNinjectModules());
internal class MyNinjectModules : NinjectModule
{
public override void Load()
{
Bind<ICustomerRepository>().To<CustomerRepository>();
}
}
protected void Application_Start()
{
_kernel.Inject(Membership.Provider);
...
Is it the case that the Global.asax code isn't run while unit testing? and so my custom provider isn't being injected, hence the fail?
UPDATE
I mocked my Provider class and passed the mocked CustomerRepository object to it.
Mock<AccountMembershipProvider> provider = new Mock<AccountMembershipProvider>();
provider.Object.repository = mockCustomerRepository.Object;
I then created a setup for the method I'm trying to test:
mockCustomerRepository.Setup(m => m.IsValidLogin("me#5.com", "password")).Returns(true);
But unfortunately I'm still getting a fail every time. To answer the question about whether I need a real or mocked object for the test - I'm not fussy, I just want to get it working at the moment!
UPDATE 2
I made those changes, and while it's still failing, it has allowed me to identify the specific problem. While debugging the test, I discovered that when I call the overridden
Membership.ValidateUser(LoginModel.Email, LoginModel.Password)
The Membership.Provider is of type SqlMembershipProvider (which is presumably the default type) and consequently validation fails.
If I cast the provider to my custom provider...
((AccountMembershipProvider)Membership.Provider).ValidateUser(LoginModel.Email, LoginModel.Password)
I get an InvalidCastException when running the test. So it seems that my mocked AccountMembershipProvider isn't being used for the test and instead the default provider is being used.
I think you have identified this already in the comment:
// set your mock provider in your AccountController
However I'm not sure what you mean exactly - I don't have a property on my AccountController to assign the provider to, and i'm not injecting it into the constructor.
Your original question:
"Is it the case that the Global.asax code isn't run while unit testing? and so my custom provider isn't being injected, hence the fail?"
My answer:
Yes.
The global.asax file is used by ASP.Net and ISS at run-time. It is compiled when the server receives it's first request.
When you are testing, you aren't in the context of a ASP.Net web-application running in ISS, but rather in program running in a test session. This means your global.asax won't get called.
More importantly, when you call:
Mock<ICustomerRepository> mockCustomerRepository = new Mock<ICustomerRepository>();
Ninject won't get called the fill the import. Moq will create a mock based on the interface. No real object will be created.
Since you did not define any Setup methods, ie:
mockCustomerRepository.Setup(mock => mock.MyAuthenticateMethod()).Returns(true);
You are passing around a mock with no defined behaviour. By default these will return false. Which probably explains why you are always getting a viewresult.
What you need to do is define setup methods for the methods you need to mock.
These are the methods of CustomerRepository that will get called you when call:
target.LogIn(model);
Also note that your AccountMembershipProvider won't get it's CustomerRepository injected since NInject won't be used. If you are testing the AccountController and it's not static (Moq doesn't work with static) you should consider mocking the AccountMembershipProvider. If you can't, then you would need to supply your mocked instance of CustomerRepository to AccountMembershipProvider.repository in your tests.
Another solution, instead of creating a Moq mock, you could also manually create (with new) a real instance of CustomerRepository in your test.
You could have Ninject do it, but at this point why? You can create it yourself and you know what specific type to create.
It all boils down to if you need a mock or a real instance of the object for this test.
Update:
If your provider is mocked, there is no need to set the repository on it. When you are calling a mock, the real object won't get called.
What you need to do is something like this:
Mock<AccountMembershipProvider> provider = new Mock<AccountMembershipProvider>();
// set your mock provider in your AccountController
provider.Setup(m => m.ValidateUser("me#5.com", "password")).Returns(true);
Update 2:
I think you are pretty close to making your test work. Without seeing all of your code (test and class under test) I can't really give you anymore help. I also feel I answered your original question, but if you are still stuck you might get more help by asking a new question relating to the problem you are currently tackling.
In your code you only create controller, but not run initialization for membership. I recommend you to create your own UserService with method ValidateUser and other you need instead of static class Membership usage.

RhinoMocks: Correct way to mock property getter

I'm new to RhinoMocks, and trying to get a grasp on the syntax in addition to what is happening under the hood.
I have a user object, we'll call it User, which has a property called IsAdministrator. The value for IsAdministrator is evaluated via another class that checks the User's security permissions, and returns either true or false based on those permissions. I'm trying to mock this User class, and fake the return value for IsAdministrator in order to isolate some Unit Tests.
This is what I'm doing so far:
public void CreateSomethingIfUserHasAdminPermissions()
{
User user = _mocks.StrictMock<User>();
SetupResult.For(user.IsAdministrator).Return(true);
// do something with my User object
}
Now, I'm expecting that Rhino is going to 'fake' the call to the property getter, and just return true to me. Is this incorrect? Currently I'm getting an exception because of dependencies in the IsAdministrator property.
Can someone explain how I can achieve my goal here?
One quick note before I jump into this. Typically you want to avoid the use of a "Strict" mock because it makes for a brittle test. A strict mock will throw an exception if anything occurs that you do not explicitly tell Rhino will happen. Also I think you may be misunderstanding exactly what Rhino is doing when you make a call to create a mock. Think of it as a custom Object that has either been derived from, or implements the System.Type you defined. If you did it yourself it would look like this:
public class FakeUserType: User
{
//overriding code here
}
Since IsAdministrator is probably just a public property on the User type you can't override it in the inheriting type.
As far as your question is concerned there are multiple ways you could handle this. You could implement IsAdministrator as a virtual property on your user class as aaronjensen mentioned as follows:
public class User
{
public virtual Boolean IsAdministrator { get; set; }
}
This is an ok approach, but only if you plan on inheriting from your User class. Also if you wan't to fake other members on this class they would also have to be virtual, which is probably not the desired behavior.
Another way to accomplish this is through the use of interfaces. If it is truly the User class you are wanting to Mock then I would extract an interface from it. Your above example would look something like this:
public interface IUser
{
Boolean IsAdministrator { get; }
}
public class User : IUser
{
private UserSecurity _userSecurity = new UserSecurity();
public Boolean IsAdministrator
{
get { return _userSecurity.HasAccess("AdminPermissions"); }
}
}
public void CreateSomethingIfUserHasAdminPermissions()
{
IUser user = _mocks.StrictMock<IUser>();
SetupResult.For(user.IsAdministrator).Return(true);
// do something with my User object
}
You can get fancier if you want by using dependency injection and IOC but the basic principle is the same across the board. Typically you want your classes to depend on interfaces rather than concrete implementations anyway.
I hope this helps. I have been using RhinoMocks for a long time on a major project now so don't hesitate to ask me questions about TDD and mocking.
Make sure IsAdministrator is virtual.
Also, be sure you call _mocks.ReplayAll()
_mocks.ReplayAll() will do nothing. It is just because you use SetupResult.For() that does not count. Use Expect.Call() to be sure that your code do everything correct.

Resources