.net core xunit How verify if method was called from inherited class - unit-testing

I have a base class called BaseService, and i want to verify if method IsValid was called in my unit test.
public interface IBaseService
{
bool IsValid<Dto, DtoValidator>(Dto entityDto, DtoValidator validator) where DtoValidator : AbstractValidator<Dto>;
}
public class BaseService : IBaseService
{
protected readonly IMapper _mapper;
protected readonly INotificationService _notification;
public BaseService(
IMapper mapper,
INotificationService notification)
{
_mapper = mapper;
_notification = notification;
}
public virtual bool IsValid<Dto, DtoValidator>(Dto entityDto, DtoValidator validator) where DtoValidator : AbstractValidator<Dto>
{
var result = validator.Validate(entityDto);
foreach (var error in result.Errors)
{
_notification.Notify(error.ErrorMessage);
}
return result.IsValid;
}
}
Class that use BaseService , some parts of code was omited
public interface IAfiliadoService : IBaseService {}
public class AfiliadoService : BaseService, IAfiliadoService
{
public AfiliadoService(
IMapper mapper,
INotificationService notification) : base(mapper, notification)
{
_afiliadoRepository = afiliadoRepository;
_lojaRepository = lojaRepository;
}
public async Task<AfiliadoResponseDto> AddAsync(AddAfiliadoRequestDto request)
{
if (IsValid(request, new AddAfiliadoRequestDtoValidator()))
{
}
}
}
In my test project i created those classes
public class MockBaseService
{
public readonly Mock<IMapper> _mapper;
public readonly Mock<INotificationService> _notification;
public MockBaseService()
{
_mapper = new Mock<IMapper>();
_notification = new Mock<INotificationService>();
}
}
public class AfiliadoServiceTest : MockBaseService
{
private readonly IAfiliadoService _afiliadoService;
public AfiliadoServiceTest()
{
_afiliadoService = new AfiliadoService(
_mapper.Object,
_notification.Object);
}
[Fact]
public async Task AdicionarUsuarioComEmailQueJaExisteDeveNotificar()
{
var request = new AddAfiliadoRequestDto();
var result = await _afiliadoService.AddAsync(request);
Assert.Null(result);
_notification
.Verify(v => v.Notify(It.IsAny<string>()), Times.Once);
// Here i want verify if method IsValid was called Once, like the verification above
}
}
I tried some things but with no success.
Exemple with what i want.
var mock = new Mock<AfiliadoService>();
mock.Verify(v => v.IsValid(request, new AddAfiliadoRequestDtoValidator()), Times.Once);
var mock = new Mock<AfiliadoService>(_mapper.Object,
_notification.Object);
var result = await mock.Object.AddAsync(request);
mock.Verify(v => v.IsValid(request, new AddAfiliadoRequestDtoValidator()), Times.Once);
This last one i got the message
Message:
Moq.MockException :
Expected invocation on the mock once, but was 0 times: v => v.IsValid<AddAfiliadoRequestDto, AddAfiliadoRequestDtoValidator>(AddAfiliadoRequestDto, AddAfiliadoRequestDtoValidator)
Performed invocations:
Mock<AfiliadoService:1> (v):
BaseService.IsValid<AddAfiliadoRequestDto, AddAfiliadoRequestDtoValidator>(AddAfiliadoRequestDto, AddAfiliadoRequestDtoValidator)
What im doing wrong?
Im using .net core - 3.1
xunit - 2.4.1
Moq - 4.16.0

Related

How to Automoq concrete class dependencies through Automoq?

In my class constrctur, we had multiple concrete class dependencies. as per automoq documentation, we can only interface or abstraction.
System Under Test Class, in that ManageLocationRepository is concrete class dependency.
public class CityEventListener : IEvent<LocationChangeEventData>
{
private readonly ILocationAdapterCaller _locationAdapterCaller;
private readonly ManageLocationRepository _managerLocationRepository;
public CityEventListener(ILocationAdapterCaller locationAdapterCaller, ManageLocationRepository managerLocationRepository)
{
_locationAdapterCaller = locationAdapterCaller;
_managerLocationRepository = managerLocationRepository;
}
public async Task<bool> ProcessEvent(LocationChangeEventData eventData)
{
}
}
Test Case -
[Theory(DisplayName = "Valid value test")]
[ClassAutoMoqData(typeof(ValidValueTests))]
public async Task ProcessEvent_WithCreateOrUpdateOperation_CallsUpsertCityAndReturnsResult(ExpectedValueTestData<Parameters, bool> data,
[Frozen] Mock<ILocationAdapterCaller> locationAdapterCallerMock, [Frozen] Mock<ManageLocationRepository> managerLocationRepositoryMock,
CityEventListener sut)
{
// fakes
var cityDetail = _fixture.Build<CityDetail>()
.With(x => x.Id, data.Params.locationChangeEventData.Id).Create();
// Arrange
locationAdapterCallerMock.Setup(mock => mock.GetCityDetail(data.Params.locationChangeEventData.Id))
.ReturnsAsync(cityDetail).Verifiable();
managerLocationRepositoryMock
.Setup(mock => mock.UpsertCity(cityDetail))
.ReturnsAsync(data.ExpectedValue).Verifiable();
var result = await sut.ProcessEvent(data.Params.locationChangeEventData);
// Assert
using (new AssertionScope())
{
Assert.IsType<bool>(result);
Assert.Equal(data.ExpectedValue, result);
locationAdapterCallerMock.Verify();
managerLocationRepositoryMock.Verify();
}
}
ClassAutoMoq Attribute
public class ClassAutoMoqDataAttribute : CompositeDataAttribute
{
public ClassAutoMoqDataAttribute(Type values)
: base(new ClassDataAttribute(values), new AutoMoqDataAttribute())
{
}
}
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute() : base(() =>
{
var fixture = new Fixture().Customize(new CompositeCustomization(
new AutoMoqCustomization() { ConfigureMembers = true, GenerateDelegates = true },
new SupportMutableValueTypesCustomization()));
fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList().ForEach(b => fixture.Behaviors.Remove(b));
fixture.Behaviors.Add(new OmitOnRecursionBehavior());
return fixture;
})
{
}
}
what are the alternate way to moq such dependencies through automoq attribute.
I solved my problem by taking two actions -
mark concrete class method virtual
create custom class automoq attribute to freeze dependencies
public class CityEventListenerClassAutoMoqAttribute : CompositeDataAttribute
{
public CityEventListenerClassAutoMoqAttribute(Type values)
: base(new ClassDataAttribute(values), new CityEventListenerAutoMoqAttribute())
{
}
}
public class CityEventListenerAutoMoqAttribute : AutoDataAttribute
{
public CityEventListenerAutoMoqAttribute()
: base(() =>
{
var fixture = new Fixture().Customize(new CompositeCustomization(
new AutoMoqCustomization() { ConfigureMembers = true, GenerateDelegates = true },
new SupportMutableValueTypesCustomization()));
var managerLocationRepositoryMock =
fixture.Freeze<Mock<ManageLocationRepository>>();
fixture.Inject(managerLocationRepositoryMock.Object);
return fixture;
})
{
}
}
Now my test case looks like this -
[Theory(DisplayName = "Valid value test")]
[CityEventListenerClassAutoMoq(typeof(ValidValueTests))]
public async Task ProcessEvent_WithCreateOrUpdateOperation_CallsUpsertCityAndReturnsResult(ExpectedValueTestData<Parameters, bool> data,
[Frozen] Mock<ILocationAdapterCaller> locationAdapterCallerMock, [Frozen] Mock<ManageLocationRepository> managerLocationRepositoryMock,
CityEventListener sut)
{
// fakes
var cityDetail = _fixture.Build<CityDetail>()
.With(x => x.Id, data.Params.locationChangeEventData.Id).Create();
// Arrange
locationAdapterCallerMock.Setup(mock => mock.GetCityDetail(data.Params.locationChangeEventData.Id))
.ReturnsAsync(cityDetail).Verifiable();
managerLocationRepositoryMock
.Setup(mock => mock.UpsertCity(cityDetail))
.ReturnsAsync(data.ExpectedValue).Verifiable();
var result = await sut.ProcessEvent(data.Params.locationChangeEventData);
// Assert
using (new AssertionScope())
{
Assert.IsType<bool>(result);
Assert.Equal(data.ExpectedValue, result);
locationAdapterCallerMock.Verify();
managerLocationRepositoryMock.Verify();
}
}
Do let me know if I can improve anything in my approach.

Unit testing view model that uses SelectMany to call an async method in ReactiveUI

I am new to ReactiveUI and trying to test a view model that looks like this:
public interface IService
{
Task<SessionModel> GetData(string id);
}
/// Provides a group of schedulers available to be used
public interface ISchedulers
{
IScheduler Default { get; }
IScheduler Dispatcher { get; }
}
public class MyVm : ReactiveObject
{
IService service;
public MyVm(ISchedulers schedulers, IService service)
{
this.service = service;
this.session = this.WhenAnyValue(x => x.SessionId)
.SelectMany(SearchSession)
.ObserveOn(schedulers.Default)
.ToProperty(this, x => x.Session);
}
private async Task<SessionModel> SearchSession(string id)
{
return await this.service.GetData(id);
}
private string sessionId;
public string SessionId
{
get => sessionId;
set => this.RaiseAndSetIfChanged(ref sessionId, value);
}
readonly ObservableAsPropertyHelper<SessionModel> session;
public SessionModel Session
{
get { return session.Value; }
}
}
public class SessionModel { }
I'm mocking the service call to return dummy data, but not sure what I need to do with a TestScheduler in order to get the SelectMany to work.
Here's a test class that shows how i would create a test for the view model. The goal is to eventually be able to check that the model got set:
[TestClass]
public class MyVmTests
{
[TestMethod]
public void CreateClass
{
var subject = new MyVm(/*pass in mocks*/);
subject.SessionId="test";
Assert.IsNotNull(subject.Session);
}
}
I don't think using TestScheduler is necessary. The following passes for me (using Moq):
var mockSchedulers = new Mock<ISchedulers>();
mockSchedulers.Setup(s => s.Default).Returns(Scheduler.Immediate);
var id = "123";
var mockService = new Mock<IService>();
var returnSession = new SessionModel();
mockService.Setup(s => s.GetData(It.Is<string>(i => i == id)))
.ReturnsAsync(returnSession);
var target = new MyVm(mockSchedulers.Object, mockService.Object);
target.SessionId = id;
Assert.IsNotNull(target.Session);
Assert.AreEqual(returnSession, target.Session);
TestScheduler is best when you're trying to test something with time (like a Delay, proving that the Delay actually happened). You're not really doing that here.

how to resolve dependency injection in xunit?

I have a problem in creating a test unit using xunit for my services that use dependency injection.
How can i send my dependency to test class?
[Fact]
public async Task GetAllRequestsHavePagingNoFilterNoSortAsync()
{
requestViewModel.RemotePaging = true;
requestViewModel.PageSize = 10;
requestViewModel.Page = 1;
var x = await requestService.GetAsync(requestViewModel);
Assert.NotNull(x);
Assert.True(x.PageCount == requestViewModel.PageSize);
}
You need to mock the dependencies using another library, the most popular one is Moq
So, assuming you have a class like this with a dependency injected:
public class ScrapedJobService : IScrapedJobService
{
private readonly IScrapedJobRepository _scrapedJobRepository;
public ScrapedJobService(IScrapedJobRepository scrapedJobRepository)
{
_scrapedJobRepository = scrapedJobRepository;
}
public WorkingPlace FindWorkingPlace(string title)
{
...
}
}
You need mock that dependency like this:
using Moq;
using Xunit;
private readonly ScrapedJobService _sut;
private readonly Mock<IScrapedJobRepository> _scrapedJobRepo = new Mock<IScrapedJobRepository>();
public ScrapedJobServiceTest()
{
_sut = new ScrapedJobService(_scrapedJobRepo.Object);
}
[Fact]
public void Test()
{
var result = _sut.FindWorkingPlace("Remote");
Assert.Equal(WorkingPlace.Remote, result);
}
Create a startup.cs file then map the dbcontext and the irepositoryDB specification to RepositoryDB concrete class. Dependency inject the IrepositoryDB in the xunit class constructor.
namespace XUnitTestProject1
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
var configuration = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.Development.json", false, true)
.Build();
services.AddControllers();
var connectionString = configuration.GetConnectionString("My_DbCoreConnectionString");
services.AddDbContext<MY_DB_Context>(options2 => options2.UseSqlServer(connectionString));
services.AddTransient<IRepositoryDB, RepositoryDB>();
}
}
}
XUnit
public class UnitTest1
{
private readonly IRepositoryDB _repository;
public UnitTest1(IRepositoryDB repository)
{
_repository = repository;
}
public async Task GetItems(long id)
{
IList<myItem> list= await _repository.GetItems(id);
Assert.True(list.Count>0);
}

Does the Repository connected to a Unit of Work need to be mocked for Unit Testing in ASP.NET Web API?

I have a Unit of Work pattern along with a Repo pattern to interact with the db layer (Entity Framework in this case) and then I have dependency injection going on in the controller's constructor. My question is, so I've mocked a IUnitOfWork which is what the controller interacts with, however, the Unit Of Work class actually accesses the repository so do I also have to mock a repository and if so, how would I implement this? I'm trying to complete a unit test of a basic Get controller method. I've read and watched several hours of video and articles and this is what I have so far:
class UrlControllerTests
{
[TestMethod]
public void ShouldReturnUrlList()
{
Mock<IUnitOfWork> fakeUnitOfWork = new Mock<IUnitOfWork>();
var urlController = new UrlController(fakeUnitOfWork.Object);
urlController.Get(5); //All this is just to see if we can get thru a test.
Assert.IsTrue(true);
}
IRepo
public interface IRepo<TEntity> where TEntity: class
{
TEntity Get(int id);
IEnumerable<TEntity> GetAll();
//Allows the running of lamba-style LINQ queries like the typical Entity Framework does:
IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate);
void Add(TEntity entity);
void AddRange(IEnumerable<TEntity> entities);
void Remove(TEntity entity);
void RemoveRange(IEnumerable<TEntity> entities);
}
IUnitOfWork:
public interface IUnitOfWork :IDisposable {
IRepo<Url> Urls { get; }
int Complete();
}
UnitOfWork:
public class UnitOfWork : IUnitOfWork
{
private readonly ApplicationDbContext _context;
public IRepo<Url> Urls { get; set; }
public UnitOfWork(ApplicationDbContext context)
{
_context = context;
Urls = new Repo<Url>(_context);
}
public int Complete()
{
return _context.SaveChanges();
}
public void Dispose()
{
_context.Dispose();
}
}
Repo:
public class Repo<TEntity> : IRepo<TEntity> where TEntity : class
{
protected readonly ApplicationDbContext _context;
public Repo(ApplicationDbContext context)
{
_context = context;
}
public TEntity Get(int id)
{
return _context.Set<TEntity>().Find(id);
}
//Repositories SHOULD NOT return IQueryable because otherwise other resources may
//Try to build queries
public IEnumerable<TEntity> GetAll()
{
return _context.Set<TEntity>().ToList();
}
public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
{
return _context.Set<TEntity>().Where(predicate);
}
public void Add(TEntity entity)
{
_context.Set<TEntity>().Add(entity);
}
public void AddRange(IEnumerable<TEntity> entities)
{
_context.Set<TEntity>().AddRange(entities);
}
public void Remove(TEntity entity)
{
_context.Set<TEntity>().Remove(entity);
}
public void RemoveRange(IEnumerable<TEntity> entities)
{
_context.Set<TEntity>().RemoveRange(entities);
}
}
}
I am using moq.
EDIT: What I'm trying to test:
public IHttpActionResult Get(int id)
{
var url = _unitOfWork.Urls.Get(id);
if (url == null)
{
NotFound();
}
return Ok(url);
}
The Target Method under test is dependent on the IUnitOfWork and IRepo<Url>. When creating unit tests you would normally mock the dependencies of the system under test so that it can be tested in isolation without having dependencies calling actual implementations (Integration Tests).
[TestClass]
public class UrlControllerTests {
[TestMethod]
public void Get_With_Valid_Id_Should_Return_Url() {
//Arrange
var testId = 5;
var expected = new Url { Id = testId };
var mockRepo = new Mock<IRepo<Url>>();
mockRepo.Setup(m => m.Get(testId)).Returns(expected);
var mockUnitOfWork = new Mock<IUnitOfWork>();
mockUnitOfWork.Setup(m => m.Urls).Returns(mockRepo.Object);
var sut = new UrlController(mockUnitOfWork.Object);
//Act
var actionResult = sut.Get(testId) as OkNegotiatedContentResult<Url>;
//Assert
Assert.IsNotNull(actionResult);
Assert.AreEqual(expected, actionResult.Content);
}
}
Moq is flexible enough that you could also mock the entire dependency call so that you don't necessarily have to mock the repository if you have no need for more complicated setups.
The test would then be rewritten to
[TestClass]
public class UrlControllerTests {
[TestMethod]
public void Get_With_Valid_Id_Should_Return_Url() {
//Arrange
var testId = 5;
var expected = new Url { Id = testId };
var mockUnitOfWork = new Mock<IUnitOfWork>();
mockUnitOfWork.Setup(m => m.Urls.Get(testId)).Returns(expected);
var sut = new UrlController(mockUnitOfWork.Object);
//Act
var actionResult = sut.Get(testId) as OkNegotiatedContentResult<Url>;
//Assert
Assert.IsNotNull(actionResult);
Assert.AreEqual(expected, actionResult.Content);
}
}

repository get an instance of a context from a bootstrap container

the repository is a prop of an Mvc controller, i'm trying to write a test method to check this controller,
but i get an error in the container call...
i'm new in mvc and testing.. so i dont know where to start
how can i do this?
this is how the test looks like:
public void SomeTest()
{
var controller= new SomeController();
var result = SomeController.Index();
Assert.IsNotNull(result);
}
The error i recive when i run the test
an exception of type System.NullReferenceException occurred in SomeContext.dll but was not handled in user code
Has your repository been initialized?
In your controller:
private Repository Repository {get;set;}
public ActionResult Index()
{
Repository = new Repository();
var something = Repository.DoSomeWork();
return View(something);
}
In your test class:
public void SomeTest()
{
var controller = new SomeController();
var result = controller.Index();
Assert.IsNotNull(result);
}
or if you are using dependency injection, with Ninject property injection you can try using Moq to inject the class:
public class SomeController : Controller
{
private IRepository repository;
[Inject]
public IRepository Repository
{
get { return repository; }
set { repository = value; }
}
// GET: /Some/
public ActionResult Index()
{
var someCollection = Repository.SomeMethod("some parameter");
foreach (var value in someCollection)
{
ViewData["message"] += value;
}
return View(someCollection);
}
}
and the test class with moq:
public class SomeTestClass
{
private Mock<IRepository> mockRepository;
[Test]
public void GivenSometestThenExpectSomeResult()
{
// Arrange
var controller = new SomeController();
mockRepository = new Mock<IRepository>();
mockRepository.Setup(x => x.SomeMethod(It.IsAny<string>())).Returns(new List<string>());
controller.Repository = mockRepository.Object;
// Act
ActionResult result = controller.Index();
// Assert
Assert.AreEqual("Index", result.ViewName);
}
}