I want to write a unit test that check a stream has been copied on the disk :
The problem is CopyTo method is not virtual so I can't use
inputMemoryStreamMock.Verify(c => c.CopyTo(outputMemoryStreamMock.Object));
and I don't know how to mock a stream :-/
here is my test method :
[TestMethod]
public void Save_Stream_On_DestinationPath()
{
// Arrange
string fileName = "filename.pdf";
DateTime date = new DateTime(2013, 9, 27);
var serverConfigMock = new Mock<IServerConfigurationManager>();
serverConfigMock.Setup(config => config.ReportingBasePath).Returns(#"c:\reportsFolder");
var factoryReportFileResultMock = new Mock<IReportFileResultFactory>();
var timeManagementMock = new Mock<ITimeManagement>();
timeManagementMock.Setup(c => c.GetServerDate()).Returns(date);
var fileSystemMock = new Mock<IFileSystem>();
var fileInfoFactory = new Mock<IFileInfoFactory>();
var directoryInfoBaseMock = new Mock<DirectoryInfoBase>();
var inputMemoryStreamMock = new Mock<Stream>();
var outputMemoryStreamMock = new Mock<Stream>();
var reportFileHelper = new ReportFileHelper(serverConfigMock.Object, factoryReportFileResultMock.Object, fileSystemMock.Object);
inputMemoryStreamMock.Setup(c => c.CanRead).Returns(true);
outputMemoryStreamMock.Setup(c => c.CanWrite).Returns(true);
outputMemoryStreamMock.Setup(c => c.CanWrite).Returns(true);
fileSystemMock.Setup(c => c.FileInfo).Returns(fileInfoFactory.Object);
fileSystemMock.Setup(c => c.File.Create(It.IsAny<string>())).Returns(outputMemoryStreamMock.Object);
fileSystemMock.Setup(c => c.Directory.CreateDirectory(It.IsAny<string>())).Returns(directoryInfoBaseMock.Object);
// Act
reportFileHelper.Save(inputMemoryStreamMock.Object, fileName, timeManagementMock.Object);
// Assert
inputMemoryStreamMock.Verify(c => c.CopyTo(outputMemoryStreamMock.Object));
}
And here is the method to test :
public void Save(Stream portfolioReportFileInfoBase, string destinationName, ITimeManagement timeManagement)
{
string destinationPath = GetDestinationPath(timeManagement);
string destinationFileUri = Path.Combine(destinationPath, destinationName);
FileSystem.Directory.CreateDirectory(destinationPath);
using (var fileStream = FileSystem.File.Create(destinationFileUri))
{
portfolioReportFileInfoBase.CopyTo(fileStream);
}
}
Thank you
My take on a couple of things :
Readability
I'm not sure your test reads very nicely. Why do you declare a fileName variable as though it were important while you don't even assert on it ? Same goes for date. This clutters your test with unneeded detail. Inline values or Anonymous Variables allow for a better signal/noise ratio.
Then why do you set up CreateDirectory() to return something ? You never use that return value, do you ? I suggest you get rid of that and the directoryInfoBaseMock variable. Same with FileInfo and fileInfoFactory. Your test needs to contain the bare minimum to set up the objects you want to verify, and nothing more. If you need to build a deep, complex graph of objects just to test one simple thing, there's generally a problem somewhere.
Design
The second thing that raises an alarm is that Save() mixes multiple language levels. When you read it, it seems to be at the same time about :
Portfolios and reports
Time management
A lot of lower level filesystem stuff
This is often a sign that an object tries to handle too much, violating the Single Responsibility Principle.
What I would do is distribute these responsibilities across separate objects.
Why does Save() need to know about time management ? Sure, we use time management to compute the destination path, but wouldn't it be better aligned with the language level and responsibility level of a Save() method if we directly passed it the destination path instead ?
Why does Save() need to know about portfolios and reports ? Well, there's basically no reason. You could just rename portfolioReportFileInfoBase to... stream.
Save() and GetPath() could then be moved to a separate lower-level filesystem wrapper class (IFileSystem is a perfect candidate), removing the tight coupling between ReportFileHelper and the filesystem.
Don't try to test that your report is written to the disk using mocks. Do it with an integration test. Don't mock types you don't own. Use mocks only to test how your own classes talk to each other. Wrap external libraries/platforms into wrapper objects, and write integration tests at the boundaries of your application to verify that your wrappers play well with those external libraries/platforms.
You'll have to use an isolation framework like TypeMock Isolator or Microsoft Fakes to test this case if you're not willing to change the code of the Save method, since CopyTo can't be mocked by Moq.
You already encapsulated access to the filesystem behind IFileSystem; why not just add a method like CopyStreamToPath?
public void Save(Stream portfolioReportFileInfoBase, string destinationName, ITimeManagement timeManagement)
{
string destinationPath = GetDestinationPath(timeManagement);
string destinationFileUri = Path.Combine(destinationPath, destinationName);
FileSystem.Directory.CreateDirectory(destinationPath);
FileSystem.CopyStreamToPath(portfolioReportFileInfoBase, destinationFileUri);
}
and the test:
fileSystemMock.Verify(c => c.CopyStreamToPath(inputMemoryStreamMock.object, It.IsAny<string>()));
Related
Unit test related question
Encountered a problem with testing scala objects that extend another trait/class that has a DB connection (or any other "external" call)
Using a singleton with a DB connection anywhere in my project makes unit-test not be a option because I cannot override / mock the DB connection
This results in changing my design only for test purpose in situations where its clearly needed to be a object
Any suggestions ?
Code snippet for a non testable code :
object How2TestThis extends SomeDBconnection {
val somethingUsingDB = {
getStuff.map(//some logic)
}
val moreThigs {
//more things
}
}
trait SomeDBconnection {
import DBstuff._
val db = connection(someDB)
val getStuff = db.getThings
}
One of the options is to use cake pattern to require some DB connection and mixin specific implementation as desired. For example:
import java.sql.Connection
// Defines general DB connection interface for your application
trait DbConnection {
def getConnection: Connection
}
// Concrete implementation for production/dev environment for example
trait ProductionDbConnectionImpl extends DbConnection {
def getConnection: Connection = ???
}
// Common code that uses that DB connection and needs to be tested.
trait DbConsumer {
this: DbConnection =>
def runDb(sql: String): Unit = {
getConnection.prepareStatement(sql).execute()
}
}
...
// Somewhere in production code when you set everything up in init or main you
// pick concrete db provider
val prodDbConsumer = new DbConsumer with ProductionDbConnectionImpl
prodDbConsumer.runDb("select * from sometable")
...
// Somewhere in test code you mock or stub DB connection ...
val testDbConsumer = new DbConsumer with DbConnection { def getConnection = ??? }
testDbConsumer.runDb("select * from sometable")
If you have to use a singleton/Scala object you can have a lazy val or some init(): Unit method that sets connection up.
Another approach would be to use some sort of injector. For example look at Lift code:
package net.liftweb.http
/**
* A base trait for a Factory. A Factory is both an Injector and
* a collection of FactorMaker instances. The FactoryMaker instances auto-register
* with the Injector. This provides both concrete Maker/Vender functionality as
* well as Injector functionality.
*/
trait Factory extends SimpleInjector
Then somewhere in your code you use this vendor like this:
val identifier = new FactoryMaker[MongoIdentifier](DefaultMongoIdentifier) {}
And then in places where you actually have to get access to DB:
identifier.vend
You can supply alternative provider in tests by surrounding your code with:
identifier.doWith(mongoId) { <your test code> }
which can be conveniently used with specs2 Around context for example:
implicit val dbContext new Around {
def around[T: AsResult](t: => T): Result = {
val mongoId = new MongoIdentifier {
def jndiName: String = dbName
}
identifier.doWith(mongoId) {
AsResult(t)
}
}
}
It's pretty cool because it's implemented in Scala without any special bytecode or JVM hacks.
If you think first 2 options are too complicated and you have a small app you can use Properties file/cmd args to let you know if you are running in test or production mode. Again the idea comes from Lift :). You can easily implement it yourself, but here how you can do it with Lift Props:
// your generic DB code:
val jdbcUrl: String = Props.get("jdbc.url", "jdbc:postgresql:database")
You can have 2 props files:
production.default.props
jdbc.url=jdbc:postgresql:database
test.default.props
jdbc.url=jdbc:h2
Lift will automatically detect run mode Props.mode and pick the right props file to read. You can set run mode with JVM cmd args.
So in this case you can either connect to in-memory DB or just read run mode and set your connection in code accordingly (mock, stub, uninitialized, etc).
Use regular IOC pattern - pass dependencies via constructor arguments to the class. Don't use an object. This gets inconvenient quickly unless you use special dependency injection frameworks.
Some suggestions:
Use object for something that can't have an alternative implementation and if this only implementation will work in all environments. Use object for constants and pure FP non side effecting code. Use singletons for wiring things up at the last moment - like a class with main, not somewhere deep in the code where many components depend on it unless it has no side effects or it uses something like stackable/injectable vendor providers (see Lift).
Conclusion:
You can't mock an object or override its implementation. You need to design your code to be testable and some of the options for it are listed above. It's a good practice to make your code flexible with easily composable parts not only for the purposes of testing but also for reusability and maintainability.
I want a unit test that verifies 2 function calls happen in the correct order. In the example, the first function encrypts a file and saves it to the file system, and the second function sends the encrypted file to a 3rd party processor (via FTP).
I am using NSubstitute as the mock framework and FluentAssertions to aid in test verification. It does not seem like this is something you can achieve with NSubstitute out of the box.
public void SendUploadToProcessor(Stream stream, string filename)
{
var encryptedFilename = FilenameBuilder.BuildEncryptedFilename(filename);
FileEncrypter.Encrypt(stream, filename, encryptedFilename);
FileTransferProxy.SendUpload(encryptedFilename);
}
[TestMethod, TestCategory("BVT")]
public void TheEncryptedFileIsSent()
{
var stream = new MemoryStream();
var filename = Fixture.Create<string>();
var encryptedFilename = Fixture.Create<string>();
FilenameBuilder
.BuildEncryptedFilename(Arg.Any<string>())
.Returns(encryptedFilename);
Sut.SendUploadToProcessor(stream, filename);
// Something here to verify FileEncrypter.Encrypt() gets called first
FileTransferProxy
.Received()
.SendUpload(encryptedFilename);
}
Try Received.InOrder in the NSubstitute.Experimental namespace.
Something like this (I haven't tested this):
Received.InOrder(() => {
FileEncrypter.Encrypt(stream, filename, encryptedFilename);
FileTransferProxy.SendUpload(encryptedFilename);
});
If you're not comfortable relying on experimental functionality, you will need to set up callbacks to store calls in order, then assert on that.
var calls = new List<string>(); //or an enum for different calls
FileEncrypter.When(x => x.Encrypt(stream, filename, encryptedFilename))
.Do(x => calls.Add("encrypt"));
FileTransferProxy.When(x => x.SendUpload(encryptedFilename))
.Do(x => calls.Add("upload"));
// Act
// Assert calls contains "encrypt","upload" in the correct order
If you do end up trying Received.InOrder, please leave some feedback on the discussion group. If we get some feedback about it working well for others then we can promote it to the core namespace.
Although it is not an answer persee, but verifying the explicit order as part of a unit test is bad practice. You should never test the implementation details. Just make sure the input is properly converted to the output and add some alternative scenarios that basically proof the expected behavior. That's the precise reason why this functionality was deprecated in RhinoMocks and that FakeItEasy doesn't even support it.
I have a complex object that I'm trying to fake.
interface IContext
{
User User { get; }
}
A.CallTo(
() => _fakeContext.User.Subscription.Attributes)
.Returns(new List<Attribute>());
But I get the next exception:
The current proxy generator can not intercept the specified method for the following reasons: - Non virtual methods can not be intercepted
All nested types are properties, and they are simple anemic types with get; set; property modifiers. And when I look into the debugger they all are fakes.
Is there any way to setup the last property of the chain and avoid setuping all previous ones?
If your objects are anemic enough, you might want to give AutoFixture a go:
var fake = A.Fake<>();
var fixture = new Fixture();
// If it's possible [1], AutoFixture will generate entire object graph
var user = fixture.CreateAnonymous<User>();
// Since data will be random [2], you can overwrite properties as you like
user.User.Subscription.Attributes = new List<Attributes>();
A.CallTo(() => fake.User).Returns(user);
In order for it to work, your custom objects need to have public constructor and preferably avoid using interfaces (but that can be mitigated with auto-mocking extensions, like AutoFakeItEasy).
The .Build method provides fluent API to customize objects autogeneration, so the randomness can be controlled
A second MSpec question from me in a day, this is a new record. I'm trying to get smart on MSpec very quickly and I've run into some old problems I've always had with MSpec.
Scenario: I have a repository that contains a bunch of cartoons. Right now I only need to filter this set on a single Name parameter, which is a string. As I'm told I'll need to filter this on more properties later on, I decide to create a class which takes in my ICartoonRepository via IoC, and contains a simple method that's called GetByName(string name).
You might argue this is overkill, but I'm trying to teach myself how to use MSpec and work in a more TDD manner.
So I create the following:
[Subject(typeof(CartoonViewModelBuilder))]
public class when_cartoon_repository_is_asked_to_get_by_id : specification_for_cartoon_viewmodel_builder
{
static string name;
static Cartoon the_cartoon;
static Cartoon result;
Establish context = () =>
{
name = "Taz";
the_cartoon = new Cartoon();
the_cartoon_repository.Stub(r => r.GetAll().Where(x=>x.Name == name).FirstOrDefault()).Return(the_cartoon);
};
Because of = () => result = subject.GetByName(name);
It should_return_cartoon = () => result.ShouldBeTheSameAs(the_cartoon);
}
This fails on the stub as the repository is empty. I have a couple other tests that pass fine (simply testing the GetAll(), etc). Do I need to add things to the repository to test it? This is where I'm stumped, please be gentle.
Also, if I'm writing the linq statement in the stub, it seems like I'm doing it twice, in the actual implementation and in the test. Is this the point? It doesn't feel right. Is there a better way I can write this test?
For clarity sake, here is the actual implementation (I'm omitting the interface and the class, which just has one property:
public class CartoonViewModelBuilder: ICartoonViewModelBuilder
{
readonly ICartoonRepository _cartoonRepository;
public CartoonQueryObject(ICartoonRepository cartoonRepository)
{
_cartoonRepository = cartoonRepository;
}
public IList<Cartoon> GetAllCartoons()
{
return _cartoonRepository.GetAll();
}
public Cartoon GetByName(string name)
{
return _cartoonRepository.GetAll().Where(x => x.Name == name).FirstOrDefault();
}
}
Edit 1: Based on the lack of responses, I should say that if I were using something like NUnit, I would be creating a method on the testing class that was like, "LoadDummyData" and threw data into the repository, then I'd do complex filtering or view model building and sort of manually checked what happened. This made large refactoring a chore. It seems like specs allows you to avoid that?
Edit 2: Here's my corrected test which now passes. Let me know if I'm doing it right, I think I am. Thanks again for the hand holding!
static string name;
static Cartoon the_cartoon;
static Cartoon result;
static IQueryable<Cartoon> the_cartoons;
Establish context = () =>
{
name = "Taz";
the_cartoon = new Cartoon {Name = name};
the_cartoons = new List<Cartoon> {the_cartoon, new Cartoon(), new Cartoon() }.AsQueryable();
the_cartoon_repository.Stub(r => r.GetAll()).Return(the_cartoons.ToList());
};
Because of = () => result = subject.GetByName(name);
It should_return_cartoon = () => result.ShouldBeTheSameAs(the_cartoon);
Edit 3: Gave you both points, but I can only award one best answer unfortunately.
The actual reason of this test failing is the way you're mocking your repository. I would be very surprised if method chains like r.GetAll().Where(x=>x.Name == name).FirstOrDefault() could be mocked so easily, as it uses LINQ extension methods and lambda clauses. The framework should really throw NotSupported exception or something to let you know that you can't mock LINQ queries as a whole.
To mock LINQ query result, you should provide properly prepared underlying data collection, which is the starting point of LINQ query. In your example you should mock just r.GetAll() to return a collection containing your element with proper name. The actual query will run on your "mocked" data and retrieve the object you expect.
This removes the need to duplicate your LINQ query in code and in test, what is strange, as you noted.
EDIT: Code in your edit is like I've suggested, technically OK.
Anyway, by now it's a bit overkill, as you've said. Your class under test doesn't do anything beside the call to the mocked repository, so the value of that test is rather small. But it may be a good start if you're going to have some more logic in GetByName method.
If you want to test your repository implementation, don't stub it! MSpec or not, I would add a list of known items to the repository and then issue the query with GetByName. Then assert that just the item you expect was returned. I would also use ShouldEqual as the repository might work with the items you add and return a different instance, though considered equal (aggregate IDs are equal).
When code processes dates based on the current date, testing should cover edge cases such as leap years as well as the more frequent month and year boundaries.
In our code we always get the current date deep down in our classes using DateTime.Now (.NET, in our case).
How can you unit test such code?
Is this where Dependency Injection becomes very useful?
Edit
This is a slight aside, but apparently the next version of Typemock will allow faking of DateTime.Now
https://blog.typemock.com/2009/05/mockingfaking-datetimenow-in-unit-tests.html
In our code we always pull out the current date using DateTime.Now (.NET, in our case). How can you unit test such code?
This is a dependency, and a non-deterministic dependency at that. You need to divide the responsibility of the code up a little more.
Before:
There is some code that uses the current datetime to do X.
After:
There should be some code that is responsible for getting the current datetime.
There should be some code that uses a datetime to do X.
These two sets of code should not be dependent on each other.
This pattern of seperating dependencies works for other cases as well (database, filesystem, etc).
Using DI for injecting "Current Date & Time" is surely an overkill. I'd rather refactor the code to operate on arbitrary date. That is, I'd change function calculateRevenue() to function calculateRevenueOn(datetime date). This is much easier to test and use in case you need calculation for some dates other than current.
I've used the very pragmatic approach discussed by Oren Eini (aka Ayende Rahien) in his blogspots Dealing with time in tests.
There is a static class like this:
public static class SystemTime
{
public static Func<DateTime> Now = () => DateTime.Now;
}
Your code becomes:
Entity.LastChange = SystemTime.Now();
And your test would become:
SystemTime.Now = () => new DateTime(2000,1,1);
repository.ResetFailures(failedMsgs);
SystemTime.Now = () => new DateTime(2000,1,2);
var msgs = repository.GetAllReadyMessages();
Assert.AreEqual(2, msgs.Length);
Always put the core date processing logic (which is, in my experience, usually easy to isolate for this purpose) into separate methods that take the date as a parameter.
Then, in your production code you can call those and give them the current date as parameter, and still test edge cases to your heart's content in unit tests.
BTW, I've found it quite crucial to test date logic very intensively for edge cases. It eliminates (possibly catastrophic, ref. Zune) bugs that you'd never have found otherwise. Apart from the ones you mentioned, daylight savings time switches can also be problematic.
You already gave the answer. You can write a small wrapper class around datetime functions that you can then inject in the classes that need to get the current date. Replacing DateTime.Now with a call to your wrapper object.
In your tests you can then inject a stub or mock object that gives you the date you need.
Another solution might be, depending on how your code works, just pass the date as a parameter instead of burying calls to datetime.Now. This makes your code a bit more reusable because it can work on more than the current date
public interface ITimeProvider {
DateTime Now { get; }
}
public class SystemTimeProvider : ITimeProvider {
public virtual DateTime Now { get { return DateTime.Now; } }
}
public class MockTimeProvider : ITimeProvider {
public virtual DateTime Now { get; set; }
}
public class ServiceThatDependsOnTime {
protected virtual ITimeProvider { get; set; }
public ServiceThatDependsOnTime(ITimeProvider timeProvider) {
TimeProvider = timeProvider;
}
public virtual void DoSomeTimeDependentOperation() {
var now = TimeProvider.Now;
//use 'now' in some complex processing.
}
}
[Test]
public virtual void TestTheService() {
var time = new MockTimeProvider();
time.Now = DateTime.Now.AddDays(-500);
var service = new ServiceThatDependsOnTime(time);
service.DoSomeTimeDependentOperation();
//check that the service did it right.
}
you could make a mockobject that simulates the DateTime.Now
here is article with an example where DateTime.Now is being mocked: Link
Dependency injection can be a solution for this, yes.
What you will do is create, for example, an IDateTimeProvider interface with a method: GetDate(). In your production-code class you will implement return DateTime.Now.
When unit testing, as Natrium suggested, you can then replace this with a mock object, one that returns a certain date to test on.
Why not use Fakes? With Visual Studio is as easy as possible. Just add a fake assembly to System, add the ShimsContext to your test,
using (ShimsContext.Create())
{
And set the DateTime.Now to return a specific value:
System.Fakes.ShimDateTime.NowGet = () => new DateTime(2000, 1, 1);
This approach makes sure every call to DateTime.Now is redirected to your code, so you don't have to inject anything to get the current time (which should be really straightfoward) nor you need a global, writable, variable.