basic assertions about unit testing - c#

Given the function below - would I be able to assert if the Value "value" was deleted from the user? Or is that assertion part of the tests on the UserService?
Also, what assertions could I test from the function?
public IHttpActionResult Post(string value)
{
var user = authorizationService.GetCurrentUser();
var isDeleted = userService.DeleteValue(value, user);
if (!isDeleted)
{
return NotFound();
}
userService.DeleteProperty(value, user);
var identityResult = userService.Update(user);
if (identityResult.Succeeded)
{
return Ok();
}
return InternalServerError();
}

Yes, you can test that: a unit test doesn't have to be the smallest possible unit per sé but that it may also contain another unit inside of it. By writing tests for both these scenarios you're essentially making a layered project where you have separate tests for the different layers and the value they add to your chain.
You could make the analogy with VAT in a production chain where each test will test the value added in each segment. More information on that here.
This translates to your question as: yes, you can (and should) test whether this action method does what it is supposed to do.
A few examples of tests you could do:
value is null
value is not in the expect format (numeric, negative value, special characters)
The user is not found
a valid value will display Ok()
What you will have to do is make sure that you are not testing against a production database but instead use in-memory repositories (mocking, faking, stubbing, seaming, you name it).
By having these tests in your controller and inside your userService you will know the exact location of the problem in case it isn't working as you want it to:
Test for: Controller Service Conclusion
Works Works Works
Works Doesn't work Faulty tests
Doesn't work Works Controller test failed
Doesn't work Doesn't work Service test failed
While not writing a test for the controller but instead relying on the service would not give you the information that your code actually works.
The line between unit-testing and other types (integration and acceptance testing mainly) is thin because you're testing a bigger part of the system but I still consider it unit-testing since it is contained to the logic of your application and does not use any external resources (database calls get mocked/stubbed/...).

Related

How to reach int variable that inside my controller method when i write unit test with xUnit

I am trying to write unit test for my controller. I am using xUnit to test my methots.
I can reach "changePasswordX" method inside my controller to test but i can not reach to my userId variable and claim value to check are they equal or not ?
How can i test this code in xUnit?
[HttpGet("ChangePassword")]
public async Task<IActionResult> ChangePassword(int userId, oldPassword, newPassword)
{
if (userId != int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value))
return Unauthorized();
_repo.changePasswordX(userId, oldPassword, newPassword);
return Ok();
}
Unit testing does not test every intermediate result of every step of a method.
Unit testing is meant to test the overall output or return value of a method, given certain inputs.
If you need to test that single line of code, then put it in a separate location (library) where it can be called and tested.
It's not clear what you're actually trying to achieve, but this is the wrong way to be writing unit/integration tests, regardless. You don't and shouldn't test the value of userId versus the claim yourself in your unit test. You know that if it doesn't match, your action returns and an UnauthorizedResult, whereas if it matches, you'll get an OkResult. If you're unit testing, you simply stub out your user principal, call the action as a method, and verify the return. If you're integration testing, the procedures mostly the same: you authorize the call, and verify that the status code is either 401 or 200, depending on which case you're testing.

How to Mock a Service with Moq and Nunit in mvc application - prevent nulls

I was under the impression that mocking is faking data calls thus nothing is real. So when I trying to create my own Unit Test that are very similar to what other developers on my team are doing, I am thinking that this is not correct to be newing up the service.
[Test]
public void TemplateService_UpdateTemplate_ContentNameNotUnique_ServiceReturnsError()
{
Template Template = new Template()
{
TemplateId = 123,
};
// Arrange.
TemplateUpdateRequest request = new TemplateUpdateRequest()
{
ExistingTemplate = Template
};
var templateRepo = new Mock<ITemplateRepository>();
var uproduceRepo = new Mock<IUProduceRepository>();
templateRepo.Setup(p => p.IsUniqueTemplateItemName(215, 456, "Content", It.IsAny<string>())).Returns(false);
templateRepo.Setup(p => p.UpdateTemplate(request)).Returns(1);
// Act.
TemplateService svc = new TemplateService(templateRepo.Object, uproduceRepo.Object);
TemplateResponse response = svc.UpdateTemplate(request);
// Assert.
Assert.IsNotNull(response);
Assert.IsNotNull(response.data);
Assert.IsNull(response.Error);
}
So my issue is with this code:
TemplateService svc = new TemplateService(templateRepo.Object, uproduceRepo.Object);
Should the TemplateService really be newed up? What "if" the Service ended up hitting a database and/or file system? Then it becomes an integration test, and no longer a unit test, right?
TemplateResponse response = svc.UpdateTemplate(request);
Also, how do I really control whether this is truly going to pass or not? It is relying on a service call that I didn't write, so what if there is a bug, or encounters a problem, or return NULL, which is exactly what I do not want! ?
If you're testing TemplateService, then YES it should be newed up. How else can you test your actual implementation? The point here is to only test TemplateService and not it's dependencies (unless it's an integrations test).
So if you got a repo like IUProduceRepository it should be mocked, simply to ensure that you're not writing to some database, and to make sure that you can create a specific scenario.
Your goal is to test that TemplateService is doing the right thing, based on a specific scenario. So let's say that your IUProduceRepository is throwing an error that your TemplateServiceshould handle. Then you should mock that error in your IUProduceRepository and test your implementation of TemplateService and make sure that it handles it as expected.
So to answer your questions...
Should the TemplateService really be newed up? What "if" the Service
ended up hitting a database and/or file system? Then it becomes an
integration test, and no longer a unit test, right?
Yes, I would say that it would be an integrations test. You mock things to make sure that the service isn't writing to DB.
Also, how do I really control whether this is truly going to pass or
not? It is relying on a service call that I didn't write, so what if
there is a bug, or encounters a problem, or return NULL, which is
exactly what I do not want! ?
Your goal is to make sure that the class you test is doing what you expect in a specific scenario. Let's say that your repo is throwing an exception for some reason, then you might want to test that your service can handle that (or at least test that it's doing what's expected).
public class TemplateService : ITemplateService
{
ITemplateRepository _templateRepo;
IUProduceRepository _produceRepo
public TemplateService(ITemplateRepository templateRepo, IUProduceRepository produceRepo)
{
_templateRepo = templateRepo;
_produceRepo = produceRepo;
}
public TemplateResponse UpdateTemplate(Template template)
{
try
{
var result = _templateRepo.Update(template);
return result;
}
catch(Exception ex)
{
// If something went wrong. Always return null. (or whatever)
return null;
}
}
}
[Test]
public void TemplateService_UpdateTemplate_ShouldReturnNullOnError()
{
Template template = new Template() // note that I changed the variable name.
{
TemplateId = 123,
};
// Arrange.
TemplateUpdateRequest request = new TemplateUpdateRequest()
{
ExistingTemplate = template
};
var templateRepo = new Mock<ITemplateRepository>();
var uproduceRepo = new Mock<IUProduceRepository>();
// Mock exception
templateRepo.Setup(p => p.UpdateTemplate(request)).Throw(new ArgumentException("Something went wrong");
// Act.
TemplateService svc = new TemplateService(templateRepo.Object, uproduceRepo.Object);
TemplateResponse response = svc.UpdateTemplate(request);
// Assert.
// Make sure that the exception is handled and null is returned instead.
Assert.IsNull(response);
}
The ONLY thing you actually tested in the case above is that your service will return null if there's an error in your repo. That way, you have designed a test for a specific scenario, and made sure that your service is doing what's expected when that scenario occurs.
I know that you specifically mentioned that you didn't want it to return null, but it's more of the concept I'm talking about. So let's say that the repo returns null... Write a test for it. Mock the repo to return null, and then test that your service is doing what it should (logging, etc).
so what if there is a bug, or encounters a problem, or return NULL,
which is exactly what I do not want! ?
That's what unit testing is all about. Find a scenario, and then make sure that the class you're testing is doing it's part. Mock your dependencies to create that specific scenario.
When I write my tests I have a lot of tests that simply asserts that a method was called. Let's say that I have a service, which only responsibility is to call the repo. Then you might want to write three tests
Test that the service actually calls the repo.
Test that the service does what it's suppose to with the value from the repo.
Test what happens if the repo throws an exception.
A unit test is designed to test a unit of functionality, which often is (but definitely need not be) a single class (since we should follow the Single Responsibility Principle). Therefore, it's fine to new up the class(es) that you're trying to test - it's the dependencies that you need to mock/stub out, which in your case is what you've done with the two repositories.
Whether your call
TemplateResponse response = svc.UpdateTemplate(request);
ends up hitting the DB is a question of using Dependency Injection correctly - your team needs to be disciplined in using explicit dependencies (ie. the repositories which are constructor injected), and not newing up repositories within a class.
And regarding whether your test is going to pass or not - if the class only has explicit dependencies (which are mocked out in your test), then only the logic within the call will be tested, which is exactly what you want!
I recommend you to read the book The Art of Unit Testing: with examples in C# to learn good practice.
In your example, you are testing TemplateService class.
Your concern is what if TemplateService calls database. It depends on how this class is implemented. From the example and mock setup, I can understand that the details of ITemplateRepository is responsible for database calling and that is why UpdateTemplate and IsUniqueTemplateItemName are mocked.
If you want to avoid the Null check, then you can check whether the svc.UpdateTemplate(request) calls the method UpdateTemplate of ITemplateRepository with its parameter.
It should be similar as follows
templateRepo.Verify(u => u.UpdateTemplate(It.Is<TemplateUpdateRequest>(r => r.ExistingTemplate.TemplateId == 123)),Times.Once);
You can verify other method calls that you have mocked.
Interaction testing is a form of unit testing where you provide fake dependencies for everything (or some things, or only the really expensive things like databases or disks, there are a lot of different interpretations regarding this) except the thing you actually want to test.
In your example, you're testing whether the TemplateService code behaves correctly. The test provides fake collaborators (the repositories), which you can setup so they return different things in different tests. That way, you can verify whether the TemplateService behaves correctly under these circumstances.
If your concerns about new-ing up the TemplateService are that there might be some remaining calls to a real database in the TemplateService code itself, that's a design issue of the TemplateService code. Those calls should not happen in the TemplateService but should be implemented on a collaborating object (exactly so you can fake them in focused isolated tests for your service).
Writing a unit test without new-ing up the system-under-test provides zero value. If every object is a fake, how can you test your actual production code?
On your point about how those mocked services are actually implemented (Do they throw nulls? Any bugs? Do they return NULL?), that's a question you can solve by
a) Writing integration tests (warning: this does not scale well, see related reading on why integrated tests are a scam).
or b) using something J.B. Rainsberger calls "Contract tests" (see related reading below) to verify whether the actual collaborator objects actually behave in a way consumers expect them to do.
Related reading:
Classicist vs. mockist testing in Martin Fowlers Mocks Aren't Stubs.
Integrated tests are a scam by J.B. Rainsberger
Contract tests by J.B.Rainsberger Who tests the contract tests?

Having difficulties setting up a mock to unit test WebAPI Post

I'm attempting to set up a unit test with MSTest and Moq for a live system that posts json from a form to a database. The system itself works just fine, but I've been tasked with attempting to build some tests for it. The ajax call in the view I'm working with goes to following HttpPost method one of the controllers:
[HttpPost]
public ActionResult Add(Request model)
{
return ProcessRequest(model, UserAction.Create);
}
Which leads to the WebAPI controller:
public int Post([FromBody]Request value)
{
try
{
var id = myRepository.AddRequest(value);
foreach (var day in value.Days)
{
day.RequestId = id;
myRepository.AddRequestDay(day);
}
return id;
}
catch
{
return -1;
}
}
With my test, I thought that using TransactionScope would be a good idea so I'm not actually saving any data on the database. If there is a better approach, please enlighten me:
[TestMethod]
public void API_Request_Post()
{
using (TransactionScope ts = new TransactionScope())
{
var jsonObject = //some json scraped from a test post
var request = new Mock<HttpRequestBase>();
//This is where I'm stuck. I can't find anything in Setup that lets me prep the Post body for when the controller gets to it.
//request.Setup(x => x.InputStream).Returns(jsonObject);
RequestController controller = new RequestController();
//This is another point that I don't understand. I make the call for post happy with a reference to the model instead of the actual json?
var result = controller.Post(new Models.Request() );
Assert.IsTrue(result > -1);
}
}
Any help trying to determine what part of the HttpRequest I need to give my json to would be greatly appreciated (and helping me understand the Post would just be icing on the cake).
Aside
I hope I'm not telling you something you already know, but it looks like you are maybe questioning where to start? That is the hardest part of testing...
Just to make sure we are on the same page, the key to knowing what to test is describing the scenario, and the key to unit testing that scenario is Isolation.
What this means is you want to isolate in regard to the class "under test".
Also, code is much easier to test if you write the test first and then the code to make that pass. You're not in that situation, so that means that the code you have MAY NOT be testable without changing it.
And finally, given any external / 3rd party system, unless you are doing an "exploratory test" then you do not want to test 3rd party stuff, namely, http posting / getting. Instead, you want to test your code and how it performs.
Assuming you knew that or that all makes sense, then, this part will be be obvious too.
Moq, or any other mocking framework, is designed to stand in for objects / services that your class under test collaborates with, in order to aid in isolation. Given two classes, ClassA and ClassB, where ClassA acts on ClassB, you want to fake/mock Class B when giving it to ClassA so you can assert / verify that ClassA behaves as you would expect for the given scenario. This seems naive at first, but consider that you will also do the same for ClassB, you then have a suite of tests that isolate in respect to what they are testing, and that gives you great coverage.
And the key to isolation is injection, make sure that if ClassA acts on ClassB, you pass ClassB in to ClassA's constructor, that way you can give it a fake class B. Class B shouldn't do anything, other than respond how you say it should respond so you can prove that ClassA behaves appropriately in that situation.
Some people frown on changing code to make it testable, but my argument is if you wrote the code to be testable in the first place, you wouldn't have to change it, so try to refactor but not reengineer.
What to Test
So, what that means is you will want a few different scenarios, each with each tests that isolate in respect to what you care about.
The key to good tests is figuring out what it is you want to test, and then arranging your tests so that it is clear what you are doing.
Test Class Name DOES NOT need to have "Test" in it; that's redundant. Explain what the scenario is instead; who is involved, etc.
The Test Method should say what the action is that you care about testing; what states are you in, etc.
** Inside the method** for now follow the "Arrange, Act, Assert" (aka Given, When, Then) approach:
Arrange: set up all of your mocks or any variables you need here, including the one class you are testing, such as your real Controller but fake myRepository and fake value
Act: do the actual action, such as Post()
Assert: Prove that the behaviors you expected happened, such as when you give it a value with four days, then you expect that:
myRepository was told to add the value
myRepository was told to add a day four times
An Example
As I'm not entirely sure what the intent of the test is there, and I don't know all of the code, I'm going to give an example that I think will relate well and will hopefully also show how to set up the mocks (and ideally why you would!)
Also if this were truly a unit test, you would usually strive for one test per assertion / verification so you do not have to debug the test, only the failing code, but I'm putting three in here for "simplicity".
In this test, you'll see that I:
Care about testing the logic in POST
So I create a mocked repository that is only used for verification it was called,
And a mocked Request that is setup to respond appropriately when called,
And I pass the mocked repository to the Controller's constructor (isolation through injection)
And then I perform the action I care about, POST, on the live controller with mocked collaborators (repository and request),
And then I verify that POST performs / behaves as expected.
[TestClass]
public class GivenAValidRequestAndRepository(){
[TestMethod]
public void WhenWeReceiveAPostRequest(){
//Arrange / Given
var repository = new Mock<IRepository>();
var request = new Mock<IRequest>();
request.Setup ( rq => rq.ToString() )
.Returns ( "This is valid json ;-)" );
request.Setup ( rq => rq.Days )
.Returns ( new List<IDay> {
"Monday",
"Tuesday",
} );
var controller = new RequestController( repository.Object );
//Act / When
int actual = controller.Post( request.Object );
//Assert / Verify
// - then we add the request to the repository
repository.Verify(
repo => repo.AddRequest( request, Times.Once() );
// - then we add the two days (from above setup) in the request to the repository
repository.Verify(
repo => repo.AddRequestDays( It.IsAny<IDay>(), Times.Exactly( 2 ));
// - then we receive a count indicating we successfully processed the request
Assert.NotEqual( -1, actual );
}
}
Closing
Your goal should not be to make your boss happy that you have written a test. Instead, strive for valuable and expressive tests that you will be able to maintain down the road. You won't get it perfect (nor should you try) just make sure that what you are testing adds value. Cover things that if they were to change in code, your test would then fail, indicating you have a bug.
I hope this helps, please reply with comments / questions.

Unit Testing Database-Modifying functions?

I have methods like this:
public static bool ChangeCaseEstimatedHours(int caseID, decimal? time)
{
Case c = Cases.Get(caseID);
if (c != null)
{
c.EstimatedHours = time;
return Cases.Update(c);
}
return false;
}
public static bool RemoveCase(int caseID)
{
return Cases.Remove(caseID);
}
which internally uses LINQ to do the queries.
I am wondering how I should go about testing these. They do not have a state so they are static. They also modify the database.
Thus, I would have to create a case, then remove it in the same test, but a unit test should only be doing 1 thing. What is usually done in these situations?
How do I test database queries, updates and deletes?
Thanks
A test that requires database access is probably the hardest test to maintain. If you can avoid touching the database in your unit test, I would try to create an interface for the Cases class.
interface ICase
{
ICase Get(int caseID);
bool RemoveCase(int caseID);
}
And then use RhinoMock, Moq to verify if the Get() and RemoveCase() were called.
If you insist you need to test with a database, then you will need to spend time on setting up a testing database and do proper data clean up.
There is a difference between "Knowing the path and walking the path". What you want to test would class as an integration test not a unit test. A unit test is something that is carried out in isolation without any external dependencies and therefore makes the test runnable even if the machine you are running it on does not have a physical database instance present on it. See more differences here.
That's why patterns like Repository are really popular when it comes to doing persistence based applications as they promote unit test-ability of the data layer via Mocking. See a sample here.
So, you have 2 options (the blue pill Or the red pill):
Blue Pill: Buy a tool like TypeMock Isolator essential or JustMock and you'll be able to mock anything in your code "and the story ends".
Red Pill: Refactor existing design of the data layer to one of the interface based patterns and use free Mocking frameworks like Moq or RhinoMocks and "see how deep the rabbit hole goes"
All the best.
Maybe you could consider approach based on Rails framework:
Initialize database tables content via presets (fixtures in Rails)
Open transaction
Run test
Rollback transaction
Go to point 2. with another test

Are those unit tests fine?

I'm trying to grasp test driven development, and I'm wondering if those unit tests is fine. I have a interface which looks like this:
public interface IEntryRepository
{
IEnumerable<Entry> FetchAll();
Entry Fetch(int id);
void Add(Entry entry);
void Delete(Entry entry);
}
And then this class which implements that interface:
public class EntryRepository : IEntryRepository
{
public List<Entry> Entries {get; set; }
public EntryRepository()
{
Entries = new List<Entry>();
}
public IEnumerable<Entry> FetchAll()
{
throw new NotImplementedException();
}
public Entry Fetch(int id)
{
return Entries.SingleOrDefault(e => e.ID == id);
}
public void Add(Entry entry)
{
Entries.Add(entry);
}
public void Delete(Entry entry)
{
Entries.Remove(entry);
}
}
Theese are the unit tests I have written so far, are they fine or should I do something different? Should i be mocking the EntryRepository?
[TestClass]
public class EntryRepositoryTests
{
private EntryRepository rep;
public EntryRepositoryTests()
{
rep = new EntryRepository();
}
[TestMethod]
public void TestAddEntry()
{
Entry e = new Entry { ID = 1, Date = DateTime.Now, Task = "Testing" };
rep.Add(e);
Assert.AreEqual(1, rep.Entries.Count, "Add entry failed");
}
[TestMethod]
public void TestRemoveEntry()
{
Entry e = new Entry { ID = 1, Date = DateTime.Now, Task = "Testing" };
rep.Add(e);
rep.Delete(e);
Assert.AreEqual(null, rep.Entries.SingleOrDefault(i => i.ID == 1), "Delete entry failed");
}
[TestMethod]
public void TestFetchEntry()
{
Entry e = new Entry { ID = 2, Date = DateTime.Now, Task = "Testing" };
rep.Add(e);
Assert.AreEqual(2, rep.Fetch(2).ID, "Fetch entry failed");
}
}
Thanks!
Just off the top of my head...
Although your testing of add really only tests the framework:
You've got adding 1 item, that's good
what about adding LOTS of items
(I mean, ridiculous amounts - for what value of n entries does the container add fail?)
what about adding no items? (null entry)
if you add items to the list, are they in a particular order?
should they be?
likewise with your fetch:
what happens in your fetch(x) if x > rep.Count ?
what happens if x < 0?
what happens if the rep is empty?
does x match performance requirements (what's it's algorithmic
complexity? is it within range when there's just one entry and when
there's a ridiculously large amount of entries?
There's a good checklist in the book Pragmatic Unit Testing (good book, highly recommended)
Are the results right?
Are all the boundary conditions CORRECT
Conform to an expected format
Ordered correctly
In a reasonable range
Does it Reference any external dependencies
Is the Cardinality correct? (right number of values)
does it complete in the correct amount of Time (real or relative)
Can you check inverse relationships
Can you cross check the results with another proven method
Can you force error conditions
Are performance characteristics within bounds
Here's some thoughts:
Positive
You're Unit Testing!
You're following the convention Arrange, Act, Assert
Negative
Where's the test to remove an entry when there's no entry?
Where's the test to fetch an entry when there's no entry?
What is supposed to happen when you add two entries and remove one? Which one should be left?
Should Entries be public. The fact that one of your asserts calls rep.Entries.SingleOrDefault suggests to me you're not constructing the class correctly.
Your test naming is a bit vague; typically a good pattern to follow is: {MethodName}_{Context}_{Expected Behavior} that remove the redundancy "test" redundancy.
As a beginner to TDD I found the book Test-Driven Development By Example to be a huge help. Second, Roy Osherove has some good Test Review video tutorials, check those out.
Before I answer, let me state that I am fairly new to unit testing and by no means an expert, so take everything I state with a grain of salt.
But I feel that your unit tests are largely redundant. Many of your methods are simple pass through, like your AddEntry method is simply a call to the underlying List method Add. Your not testing your code, your testing the Java library.
I would recommend only unit testing methods that contain logic that you write. Avoid testing obvious methods like getters and setters, because they operate at the most basic level. That's my philosophy, but I know some people do believe in testing obvious methods, I just happen to think it is pointless.
Seems fine like this. I personally like to give my tests a bit more descriptive names but that's more of a personal preference.
You can use mocking for dependencies of the class you're testing, EntryRepository is the class under test so no need to mock that, else you would end up testing the mock implementation instead of the class.
Just to give a quick example. If your EntryRepository would use a backend database to store the Entries instead of a List you could inject a mock-implementation for the data-access stuff instead of calling a real database.
This looks like a fine start, but you should try to test the 'borderline' cases as much as possible. Think about what might cause your methods to fail - Would passing a null Entry to Add or Delete be valid? Try to write tests that exercise every possible code path. Writing tests in this manner will make your test suite more useful in the future, should you make any changes to the code.
Also, it is useful for each test method to leave the test object in the same state as when it was invoked. I noticed your TestFetchEntry method adds an element to the EntryRepository, but never removes it. Having each method not affect test object state makes it easier to run series of tests.
You should not be mocking the IEntryRepository since the implementing class is the class under test. You might want to mock the List<Entry> and inject it, then just test that the methods that you invoke via your public interface are called appropriately. This would just be an alternative to the way you have it implemented and isn't necessarily better -- unless you want the class to have it's backing class injected in which case writing the tests that way would force that behavior.
You might want some more tests to make sure that when you insert an entry, the right entry is inserted. Likewise with delete -- insert a couple of entries, then delete one and make sure that the proper one has been deleted. Once you come up with tests to get the code to do what you want it to, keep thinking of ways that you could mess up writing the code and write tests to make sure those don't happen. Granted this class is pretty simple and you may be able to convince yourself that the tests you have that drive behavior is sufficient. It doesn't take much complexity, though, to make it worth testing edge cases and unexpected behavior.
For a TDD beginner and for this particular class, your tests are fine. +1 for making the effort.
Post another question once you get to more complex scenarios involving dependency injection and mocking. This is where things get really interesting ;).
Looks good overall. You should use transactions (or create new instance of repository in TestInitialize) to make sure the tests are trully isolated.
Also use more descriptive test methods, like When_a_new_entity_is_added_to_a_EntryRepository_the_total_count_of_objects_should_get_incremented

Categories