I have following class and method which i want to mock using MSTest with Moq
public AuditRepository: IAuditRepository
{
private readonly SQLDBContext _context;
public AuditRepository(SQLDBContext context)
{
_context = context;
}
public AddAuditData(Audit auditData)
{
var isAuditEnabled = from s in context.settings
where s.Name = "AuditEnabled" select s.value;
if(isAuditEnabled )
{
context.AddObject(typeof(AuditData).Name,auditData);
context.SaveChanges();
}
}
}
The SQLDBContext is like
public partial class SQLDBContext :ObjectContext
{
//..EF5 stuff
}
Related
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
I want to make a webapi and I'm trying to do it through the services way, I have a repository generic and another 2 repository and a unit of work, apparently everything goes fine, but when I run and test the webapi from postman I got that error:
InvalidOperationException: Unable to resolve service for type 'Api.Repository.Repositories.UnitOfWork' while attempting to activate 'Api.ServicesBusiness.Implementacion.EquipoServices'.
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, bool throwIfCallSiteNotFound)
Here is the my dbcontect:
public class AppDbContext : DbContext
{
public AppDbContext()
{
}
public AppDbContext(DbContextOptions<AppDbContext> option) :base(option)
{
}
public DbSet<Equipo> Equipos { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer("Server=(localdb)\\Express;Database=SoftballLeague;Trusted_Connection=True");
}
}
}
Here is the interface of my generic repository:
public interface IGenericRepository<T> where T : class
{
Task<T> AddAsyn(T t);
Task<T> UpdateAsyn(T t, object key);
}
Here is the implementation of my generic repository:
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
private readonly AppDbContext _context;
private readonly DbSet<T> _dbSet;
public GenericRepository(AppDbContext context)
{
_context = context;
_dbSet = _context.Set<T>();
}
public virtual async Task<T> AddAsyn(T t)
{
_dbSet.Add(t);
await _context.SaveChangesAsync();
return t;
}
public virtual async Task<T> UpdateAsyn(T t, object key)
{
if (t == null)
return null;
T exist = await _dbSet.FindAsync(key);
if (exist != null)
{
_context.Entry(exist).CurrentValues.SetValues(t);
await _context.SaveChangesAsync();
}
return exist;
}
}
Here is the interface of my equipo repository:
public interface IEquipoRepository:IGenericRepository<Team>
{
int GetAverageTeam(string name);
int GetTeamHit(string name);
}
Here is the implementation of my equipo repository:
public class EquipoRepository : GenericRepository<Team>, IEquipoRepository
{
private readonly AppDbContext dbContext;
public EquipoRepository(AppDbContext context) : base(context)
{
this.dbContext = context;
}
public int GetAverageTeam(string name)
{
int teamAverage = 0;
var resultAverage = this.dbContext.Equipos
//.SelectMany(bItem => bItem.)
.Where(equipo=>equipo.Nombre==name)
.SelectMany(equipo => equipo.jugadores)
.Average(jugador => jugador.Average);
if (resultAverage.HasValue)
teamAverage =Convert.ToInt32(Math.Round(resultAverage.Value));
return teamAverage;
}
public int GetTeamHit(string name)
{
int resultTotal = 0;
var result = this.dbContext.Equipos
//.SelectMany(bItem => bItem.)
.Where(equipo => equipo.Nombre == name)
.SelectMany(equipo => equipo.jugadores)
.Sum(jugador => jugador.Cant_Hits_Conectados);
if (result.HasValue)
resultTotal = result.Value;
return resultTotal;
}
}
Here is the interface of my unit of work:
public interface IUnitOfWork:IDisposable
{
Task Commit();
}
Here is the implementation of my unit of work:
public class UnitOfWork : IUnitOfWork
{
private readonly AppDbContext _DbContext;
private EquipoRepository equipoRepository ;
public UnitOfWork(AppDbContext dbContext)
{
this._DbContext = dbContext;
this.equipoRepository = new EquipoRepository(this._DbContext);
}
public EquipoRepository GetEquipoRepository{
get {
if(this.equipoRepository==null)
this.equipoRepository= new EquipoRepository(this._DbContext);
return this.equipoRepository;
}
}
public async Task Commit()
{
await this._DbContext.SaveChangesAsync();
}
public void Dispose()
{
this._DbContext.Dispose();
}
}
Here is the implementation of services interfaces IEquipoServices:
public interface IEquipoServices
{
ICollection<EstadisticaEquipoModel>AveragePorEquipo(string name);
int Total2bleConectados(string name);
}
Here is the implementation of services EquipoServices which is the one who throws the error:
public class EquipoServices : IEquipoServices
{
private readonly UnitOfWork unit;
public EquipoServices(UnitOfWork unitOfWorkFactory)
{
this.unit = unitOfWorkFactory;
}
public ICollection<EstadisticaEquipoModel> AveragePorEquipo(string name)
{
var equipoAverage= this.unit.GetEquipoRepository.GetAverageEquipo(name);
return equipoAverage;
}
public int AveragePorEquipo(string name)
{
var result = this.unit.GetEquipoRepository.GetEquipoTotal2bleConectados(name);
return result;
}
}
This is the controller, here I am just running the ListadoEquipos() method:
[Route("api/[controller]")]
public class EquipoController : ControllerBase
{
private readonly IEquipoServices equipoService;
private readonly IMapper _mapper;
public EquipoController(IEquipoServices eqService, IMapper mapper)
{
this.equipoService = eqService;
this._mapper = mapper;
}
[HttpGet("list")]
public IEnumerable<string> ListadoEquipos()
{
return new string[] { "value1", "value2" };
}
}
This is the configuration in the startup.cs file:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<AppDbContext>(options=>options.UseSqlServer(Configuration.GetConnectionString("ConnectionString")));
services.AddTransient<IUnitOfWork, UnitOfWork>();
services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));
services.AddSingleton<IEquipoServices, EquipoServices>();
//services.AddScoped<IJu, JugadorService>();
services.AddAutoMapper(typeof(Startup));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
You registered IUnitOfWork, but you're injecting UnitOfWork. The service collection doesn't know how to inject UnitOfWork directly.
Long and short, inject IUnitOfWork instead:
private readonly IUnitOfWork unit;
public EquipoServices(IUnitOfWork unitOfWorkFactory)
I'm trying to refactor one pretty old project, so I started implementing new architecture (MVVM) with Dagger2, RxJava, RxAndroid... Now everything is connected and working fine, now the problem is, I have no idea how to write a Unit test for my ViewModel..
I want to start with Login screen first, so I created a LoginViewModel, but first let me show you what I did..
I have a DataModule that provides 2 classes, RestApiRepository and ViewModelFactory. RestApiRepository looks like this:
public class RestApiRepository {
private RestClient restClient;
public RestApiRepository(RestClient restClient) {
this.restClient = restClient;
}
public Observable<AuthResponseEntity> authenticate(String header, AuthRequestEntity requestEntity) {
return restClient.postAuthObservable(header, requestEntity);
}
}
Rest client with api call for login:
public interface RestClient {
#POST(AUTH_URL)
Observable<AuthResponseEntity> postAuthObservable(#Header("Authorization") String authKey, #Body AuthRequestEntity requestEntity);
}
Second class from DataModule is ViewModelFactory:
#Singleton
public class ViewModelFactory extends ViewModelProvider.NewInstanceFactory implements ViewModelProvider.Factory {
private RestApiRepository repository;
#Inject
public ViewModelFactory(RestApiRepository repository) {
this.repository = repository;
}
#NonNull
#Override
public <T extends ViewModel> T create(#NonNull Class<T> modelClass) {
if (modelClass.isAssignableFrom(LoginViewModel.class)) {
return (T) new LoginViewModel(repository);
}
throw new IllegalArgumentException("Unknown class name");
}
}
And finally, LoginViewModel:
public class LoginViewModel extends ViewModel {
private final CompositeDisposable disposable = new CompositeDisposable();
private final MutableLiveData<AuthResponseEntity> responseLiveData = new MutableLiveData<>();
private RestApiRepository restApiRepository;
private SchedulerProvider provider;
public LoginViewModel(RestApiRepository restApiRepository, SchedulerProvider provider) {
this.restApiRepository = restApiRepository;
this.provider = provider;
}
public MutableLiveData<AuthResponseEntity> getResponseLiveData() {
return responseLiveData;
}
#Override
protected void onCleared() {
disposable.clear();
}
public void auth(String token, AuthRequestEntity requestEntity) {
if (token != null && requestEntity != null) {
disposable.add(restApiRepository.authenticate(token, requestEntity)
.subscribeOn(provider.io())
.observeOn(provider.ui())
.subscribeWith(new DisposableObserver<AuthResponseEntity>() {
#Override
public void onNext(AuthResponseEntity authResponseEntity) {
responseLiveData.setValue(authResponseEntity);
}
#Override
public void onError(Throwable e) {
AuthResponseEntity authResponseEntity = new AuthResponseEntity();
authResponseEntity.setErrorMessage(e.getMessage());
responseLiveData.setValue(authResponseEntity);
}
#Override
public void onComplete() {
}
}
));
}
}
}
So, I'm sure everything is connected well, I can successfuly login...
For the RxAndroid test issues, I found somewhere that I have to use this Scheduler provider like this:
public class AppSchedulerProvider implements SchedulerProvider {
public AppSchedulerProvider() {
}
#Override
public Scheduler computation() {
return Schedulers.trampoline();
}
#Override
public Scheduler io() {
return Schedulers.trampoline();
}
#Override
public Scheduler ui() {
return Schedulers.trampoline();
}
}
Below is my LoginViewModelTest class, but I don't know how to handle RxJava/RxAndroid inside the tests..
#RunWith(MockitoJUnitRunner.class)
public class LoginViewModelTest {
#Mock
private RestApiRepository restApiRepository;
#Mock
private MutableLiveData<AuthResponseEntity> mutableLiveData;
private LoginViewModel loginViewModel;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
AppSchedulerProvider schedulerProvider = new AppSchedulerProvider();
loginViewModel = Mockito.spy(new LoginViewModel(restApiRepository, schedulerProvider));
}
#Test
public void authenticate_error() {
String token = "token";
AuthRequestEntity requestEntity = Mockito.mock(AuthRequestEntity.class);
Mockito.doReturn(Observable.error(new Throwable())).when(restApiRepository).authenticate(token, requestEntity);
loginViewModel.auth(token, requestEntity);
AuthResponseEntity responseEntity = Mockito.mock(AuthResponseEntity.class);
responseEntity.setErrorMessage("Error");
Mockito.verify(mutableLiveData).setValue(responseEntity);
}
}
So, I wanted to write a test for failed case when onError is called, but when I run it, I get this error:
exclude patterns:io.reactivex.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked. See http://g.co/androidstudio/not-mocked for details.
You can mock the behaviour of restApiRepository:
Mockito.when(restApiRepository.authenticate(token, requestEntity)).thenReturn(Observable.error(error));
and verify that responseLiveData.setValue is being called with the appropriate parameters
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);
}
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);
}
}