I have some appsetting related to SendGrid Service like username, password and some resetpasswordemail settings. Now i wanted to use them in my unit test. My ResetPasswordSetting class looks like this.
public class ResetPasswordEmailSetting : IResetPasswordEmailSetting
{
public string ResetPasswordEmailUrl { get; set; }
public List<string> AddToEmails { get; set; }
public string FromEmail
{
get { return ConfigurationManager.AppSettings.Get("ResetPassword_FromEmail"); }
}
public string Subject
{
get { return ConfigurationManager.AppSettings.Get("ResetPassword_Subject"); }
}
public string SenderDisplayName
{
get { return ConfigurationManager.AppSettings.Get("ResetPassword_SenderDisplayName"); }
}
}
When i run my unit test using this class then the fields that get their value from Webconfig appsetting part are coming null.
My Unit Test looks like this.
[TestMethod]
[TestCategory("SendGrid-Service")]
public async Task email_recieved_when_correct_email_provided()
{
var sendgrid = new SendGridService();
var resetpasswordsetting = new ResetPasswordEmailSetting
{
AddToEmails = new List<string> { "fluffyduk#gmail.com" },
ResetPasswordEmailUrl = "www.google.com",
};
// when i debug then resetpasswordsetting fields are coming null other then above.
var result = await sendgrid.SendResetPasswordEmail(resetpasswordsetting, new
SendGridSettings());
result.Should().BeTrue();
}
so any idea how to get these settings in unit test.
The first thing that comes to my mind is that in this test you are NOT interested in the settings, the subject of your test is SendResetPasswordEmail method from the SendGridService class. Remember you are implementing UNIT tests, not integration tests or something like that. While unit testing you should strive to isolate any dependencies and config settings is one dependency your class doesn't really need to test a specific business logic. For this purpose you should create a mock object instead because, again, config settings are NOT needed to test a piece of functionality.
However, if you still insist in using real config files there's nothing stopping you from adding an app.config file to your unit test project and specifying all the appSettings your tests require
Related
I'd like to write the data contract validation tests in the same test surroundings as the endpoint test. Is it even possible?
The way I do it now, is to validate my DataContracts in one set of tests,
and then rely on these tests being complete when testing the Endpoint.
Doing it like this is arguably correct, but editor wise the tests are in different projects and hence harder to discover.
I know how to navigate the solution; but what about the ones following me?
Test:
[TestData(differenct_kinds_of_MyDataContract_data)]
public void MyEndpoint_Should_validate_input(input){
var sut = new MyController();
// Act.
// A clean unit test. No Invoke, no startup of Aspnet.
// But I still want the aspnet validation to trigger...
var res = await sut.MyEndpoint(input);
// Assert
res.Should.BeOfType<400BadRequest>()
}
Data contract:
[DataContract]
public class MyDataContract
{
[DataMember]
[Required]
public string MyProp{ get; set; }
}
Endpoint:
public class MyController : ControllerBase
{
public async Task<IActionResult> MyEndpoint(MyDataContract myDataContract)
{
...
}
}
C# method where I am using IMapper interface
foreach (var req in listRequestMasters)
{
var customReq = _mapper.Map<GridModel>(req);
}
by below line of code getting success assertion but not as expected result, the one record getting twice
_mockMapper.Setup(x => x.Map<GridModel>(It.IsAny<RequestMaster>())).Returns(requestGridModelMockData.FirstOrDefault());
and by below line of code getting
Message:
Moq.MockException : IMapperBase.Map(RequestMaster)
invocation failed with mock behavior Strict. All invocations on the
mock must have a corresponding setup.
_mockMapper.Setup(x => x.Map<List<GridModel>>(It.IsAny<RequestMaster>())).Returns(requestGridModelMockData);
remaining code
var result = await Service.GetHistoryRequestDetails(historyVMMockData);
Assert.Equal(JsonConvert.SerializeObject(requestGridModelMockData), JsonConvert.SerializeObject(result));
AutoMapper is a library that is already well tested on its own. So you should use the AutoMapper library also in your tests and not mock it, because you want to test your code and not others library code (or do you have also self written tests for ASP core, EF or something similar?).
In most environments you manage your mapping within individual Profiles. If not, you should do so and create within your test a fresh mapper (preferable in constructor) and use it as usual.
For example you have some DTOs:
public class Source
{
public string Name { get; set; }
}
public class Destination
{
public string Name { get; set; }
}
And somewhere else you defined the AutoMapper mappings:
public class MyProfile : Profile
{
public MyProfile()
{
CreateMap<Source, Destination>();
}
}
Then within your test class you do something like this:
public class MyTests
{
private readonly IMapper mapper;
public MyTests()
{
var config = new MapperConfiguration(cfg => cfg.AddProfile<MyProfile>());
var mapper = config.CreateMapper();
}
[Fact]
public void TestSomething()
{
var source = new Source { Name = "foo" };
var sut = new SystemUnderTest(mapper);
var result = sut.DoSomething(source);
var expected = mapper.Map<Dest>(source);
Assert.Equal(expected, result, DestinationComparer.Default);
}
}
As you can see, the system under test receives the real mapper (even if you just care for an IMapper interface). You don't create a mock, stub, puppet, you name it for 3rd party libraries. You use the real implemenations, because you write tests for your code.
Maybe it makes sense to write tests checking if a 3rd party library works as expected, which helps narrow problems down when upgrading a library and still behaves the same. But these tests don't use anything of your code and just tests some library function:
[Fact]
public void CheckMapperMapsCorrectly()
{
var source = new Source { Name = "Foo" };
var dest = mapper.Map<Destination>(source);
Assert.Equal(source.Name, dest.Name);
}
But that is something different and fully optional, depending on how much you trust each 3rd party library or makes sense if you already fall into that pit on an upgrade of a 3rd party library to avoid the same problem on next update.
How does one unit test a service which connects to a database?
I have a playerRepository class in data access layer, which interacts with the database directly, and a playerService class in business layer which creates an instance of playerRepository and services random stuff like - deleting player, saving player, getting all players, getting the player by id/name yadda yadda.
I want to unit test the playerService without using the real database, but using in-memory database provided with EF.
The problem is, I'm having trouble figuring out how to set it up.
I have a PlayerContext : DbContext class, which is used as a model to code-first (done this part via tutorial on EF). And I have to add a parameter to constructor DbContextOptionsBuilder<PlayerContext>, but I don't know where to begin. I don't know how and where to setup the connection string, where does the "default" database store itself.
I want to do this by using EF without NSubstitute or Moq, I'm doing this to learn how it's done without using other frameworks except for EF.
public class PlayerContext : DbContext
{
public PlayerContext() : base()
{
}
public DbSet<Player> Players { get; set; }
}
public class Player
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int DciNumber { get; set; }
}
I'm using visual studio provided unit testing
[TestClass]
public class PlayerServiceTest
{
// Should get all the players from database
[TestMethod]
public void GetAllPlayers()
{
// arrange - act
// TODO: Return all the players from the database
// assert
// TODO: Should return empty list
}
And the PlayerService class looks something like this
public class PlayerService
{
private PlayerRepository _playerRepository = new PlayerRepository();
public List<Player> GetAllPlayers()
{
var players = _playerRepository.GetAllPlayers();
return players;
}
PlayerRepository
public class PlayerRepository
{
public List<Player> GetAllPlayers()
{
using (var context = new PlayerContext())
{
var players = context.Players.ToList();
return players;
}
}
Generally my questions are:
How to make the PlayerContext with another connection string which connects to in-memory database in case of unit test, and also how to provide it with the correct connection string when not running via unit-tests
How to change the location of the database, because it's using a default path in C:\Users.
I'm not looking for integration tests with the DAL's PlayerRepository, I just want to test the business layer and all I need is, when I run the tests that the PlayerService to uses the PlayerRepository which connects to in-memory database and that's it. Otherwise it should connect to the local db stored in the same folder as the main exe for the app
Help needed!
The missing piece is dependency injection / IoC. The principle here is to define your dependencies (Repository) with a contract interface that can be mocked out. Inject that dependency into the classes that depend on it. This way you can substitute out concrete implementations like databases, file handling, etc. with mock up objects that return a known state, throw an expected exception, etc. to test your business logic's handling of those scenarios.
public class PlayerService
{
private readonly IPlayerRepository _playerRepository = null;
public PlayerService(IPlayerRepository playerRepository)
{
_playerRepository = playerRepository ?? throw new ArgumentNullException("playerRepository");
}
public List<Player> GetAllPlayers()
{
var players = _playerRepository.GetAllPlayers();
return players;
}
}
Have a look at IoC containers such as Autofac, Unity, Ninject, etc. for examples of how a container can be st up to automatically identify and inject concrete class instances into your services when it constructs them.
When you go to write a unit test you create a mock of the IPlayerRepository class (see: Moq for example) and pass that to your service under test. I.e.:
[Test]
public void TestService()
{
var mockRepository = new Mock<IPlayerRepository>();
mockRepository.Setup(x => x.GetPlayers()).Returns(buildTestPlayerList());
var serviceUnderTest = new PlayerService(mockRepository.Object);
// continue with test...
}
At a worst case: if you want to forgo the container, this can work as well:
public class PlayerService
{
private IPlayerRepository _playerRepository = null;
public IPlayerRepository PlayerRepository
{
get { return _playerRepository ?? (_playerRepository = new PlayerRepository()); }
set { _playerRepository = value; }
}
// ...
}
... and then with the test...
[Test]
public void TestService()
{
var mockRepository = new Mock<IPlayerRepository>();
mockRepository.Setup(x => x.GetPlayers()).Returns(buildTestPlayerList());
var serviceUnderTest = new PlayerService { PlayerRepository = mockRepository.Object };
// continue with test...
}
This is a pattern I call "lazy property injection" where you can opt to send a dependency in, but by default it will simply create the default dependency. This can be a useful pattern when introducing dependency substitution & unit testing into legacy code that was relying heavily on newing up classes mid-code. It's lazy in the sense that the dependency is only "newed" the first time it is accessed. If you call a method in the service that doesn't need the dependency then there is no initialization of every dependency, only the ones that are used. I highly recommend reading up on IoC containers though since they help automate wiring up dependencies.
I am working in an ASP.net MVC 5 application. I would like to Unit Test my controller action which looks like this
public ActionResult Search()
{
var vm = SetupSearchViewModel();
return View(vm);
}
All the hard work is done by the SetupSearchViewModel() method, which itself is an orchestrator calling many different other methods, one of which is this
private string ExtractJsonFile(string filename)
{
var filePath = HttpContext.Server.MapPath(filename);
var json = System.IO.File.ReadAllText(filePath);
return json;
}
I plan on doing many Unit Tests on this particular action, but I'm starting with a very simple Unit Test which checks that the correct type of ActionResult is returned
[Test]
public void Search_Get_ReturnsViewResult()
{
// arrange
var performanceController = PerformanceControllerInstance;
// act
var result = performanceController.Search();
//assert
Assert.IsNotNull(result as ViewResult);
}
The test is failing because of the ExtractJsonFile method. It uses HttpContext and that is null. I am using Rhino Mocks to do the mocking of the various classes.
What would be the best way to Unit Test this? Darin in this thread suggest we avoid HttpContext.Current if we want our code Unit Tested.
By the way I tried mocking the HttpContext and made it not null, but then the Server is null, I can go ahead and mock that too I suppose (I don't know how yet), but is there no better way? I've no problem doing major refactoring if needed.
HttpContext.Server.MapPath would require an underlying virtual directory provider which would not exist during the unit test. Abstract the path mapping behind a service that you can mock to make the code testable.
public interface IPathProvider {
string MapPath(string path);
}
In the implementation of the concrete service you can make your call to map the path and retrieve the file.
public class ServerPathProvider: IPathProvider {
public string MapPath(string path) {
return HttpContext.Current.Server.MapPath(path);
}
}
you would inject the abstraction into your controller or where needed and used
public MyController : Controller {
public MyController(IPathProvider pathProvider) {
this.pathProvider = pathProvider;
}
//...other code removed for brevity
private string ExtractJsonFile(string filename) {
var filePath = pathProvider.MapPath(filename);
var json = System.IO.File.ReadAllText(filePath);
return json;
}
}
Using your mocking framework of choice you can then mock the provider
[Test]
public void Search_Get_ReturnsViewResult() {
// arrange
IPathProvider mockedPathProvider = //...insert your mock/fake/stub here
var performanceController = PerformanceControllerInstance(mockedPathProvider);
// act
var result = performanceController.Search();
//assert
Assert.IsNotNull(result as ViewResult);
}
and not be coupled to HttpContext
You could even go further and refactor the entire ExtractJsonFile(string filename) into its own service to get around being tied to disk as well.
public interface IJsonProvider {
string ExtractJsonFile(string filename);
}
This service is now flexible enough to get the file from other sources like web service if needed.
I have working in unit testing in ASP.Net web application, now I have accessing my constructor in the model file to test which has Server.MapPath code for uploading my XMLfile, when try to testing this i get error, because the HttpContext is null so i have to mocking Server.MapPath.
I have searched lot but every samples given only for Asp.NET MVC but I have working in ASP.NET. so please help in ASP.NET to solve this issue.
My code is given below.
public class NugetPlatformModel
{
public bool IsHavingLicense { get; set; }
public List<PlatformProducts> PlatformProduct = new List<PlatformProducts>();
public NugetPlatformModel()
{
var xmldoc = new XmlDocument();
mldoc.Load(HttpContext.Current.Server.MapPath(#"~\Content\PlatformProducts.xml"));
}
}
And my unit testing code
[Test]
public void Account_UnlicensedCustomerIdentity_IsStudioLicenseAndIshavinglicenseFalse()
{
//Act
NugetPlatformModel nugetPlatformModel = new NugetPlatformModel();
//Assert
AssertEquals(false, nugetPlatformModel.IsHavingLicense);
}
This is typical with code that calls static methods, it's very difficult to test while preserving separation of concern and avoiding tight coupling. Here is a generic approach to test and mock "untestable code": write a "facade wrapper" to it.
Create a wrapper for these methods. A simple class that contains methods named sensibly, and only delegates to the untestable calls (typically static calls)
Create an interface to that wrapper class
Instead of directly calling the untestable methods in your client code, use the wrapper (dependency-injected using the interface provided in step 2) and call normal methods on it.
In your unit-test, mock the wrapper with the behaviour you want.
This approach effectively reduces the coupling and separates the concerns that need to be separated. Of course, you still can't test the behaviour of the wrapper itself, but if it's simple enough (only delegating to the original calls) then it's not as big a problem.
Update:
Using shims to isolate your application from other assemblies for unit testing
Shim types are one of two technologies that the Microsoft Fakes Framework uses to let you easily isolate components under test from the environment. Shims divert calls to specific methods to code that you write as part of your test. Many methods return different results dependent on external conditions, but a shim is under the control of your test and can return consistent results at every call. This makes your tests much easier to write.
Use shims to isolate your code from assemblies that are not part of your solution. To isolate components of your solution from each other, we recommend that you use stubs.
How already answered, you should decouple your system
public class NugetPlatformModel
{
public bool IsHavingLicense { get; set; }
public List<PlatformProducts> PlatformProduct = new List<PlatformProducts>();
public NugetPlatformModel(IPlatformProductProvider provider)
{
var xmldoc = new XmlDocument();
//System.Web.HttpContext.Current.Server.MapPath(#"~\Content\PlatformProducts.xml")
xmldoc.Load(provider.Filepath);
}
public interface IPlatformProductProvider
{
string Filepath { get; }
}
public class PlatformProductProvider: IPlatformProductProvider
{
string _filepath;
public string Filepath
{
get { return _filepath; }
set { _filepath = value;}
}
public PlatformProductProvider(string path)
{
_filepath = path;
}
}
}
And your test could be:
[Test]
public void Account_UnlicensedCustomerIdentity_IsStudioLicenseAndIshavinglicenseFalse()
{
//Arrange
// using Moq
//var mock = new Mock<IPlatformProductProvider>();
//IPlatformProductProvider provider = mock.Object;
//provider.Filepath = "pippo.xml";
// otherwise
var provider = new PlatformProductProvider("pippo.xml");
//Act
NugetPlatformModel nugetPlatformModel = new NugetPlatformModel(provider);
//Assert
AssertEquals(false, nugetPlatformModel.IsHavingLicense);
}
If you can't modify the source code, try using shims (https://msdn.microsoft.com/en-us/library/hh549176.aspx).