Is it possible to mock out File calls with rhino mock example:
private ServerConnection LoadConnectionDetailsFromDisk(string flowProcess)
{
var appPath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
var bodyFile = Path.Combine(appPath, #"XML\ServerConnections.xml");
if (File.Exists(bodyFile))
{
//more logic
}
So I am trying to mock the File.Exists method so it will return true, so I am able to test the next branch of logic regardless of if the file exists or not. Is this possible?
Here's your original snippet:
private ServerConnection LoadConnectionDetailsFromDisk(string flowProcess)
{
var appPath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
var bodyFile = Path.Combine(appPath, #"XML\ServerConnections.xml");
if (File.Exists(bodyFile))
{
//more logic
}
}
Instead of using the System.IO library (which is not possible to mock), cadrell was basically saying to add a layer of abstraction, which you can mock:
private ServerConnection LoadConnectionDetailsFromDisk(string flowProcess)
{
var appPath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
var bodyFile = Path.Combine(appPath, #"XML\ServerConnections.xml");
if (FileExists(bodyFile))
{
//more logic
}
}
public bool FileExists(bodyFile) { return File.Exists(bodyFile) }
Now, in your test, you can define a PartialMock that uses most of the existing code (allowing you to test it) but allows you to override just the FileExists method:
var myPartialMock = mockRepo.PartialMock(typeof(MyObject));
myPartialMock.Expect(m=>m.FileExists("")).IgnoreArguments().Return(true);
myPartialMock.LoadConnectionDetailsFromDisk("myProcess");
Now, the call from inside your if statement always returns true.
Something else to consider; I see an if block predicated on the existence of a file. You didn't specify the code, but I would bet anybody else but you (since you can change the code) that the code opens or manipulates the file we now know exists. So, the entire method rubs right up against the border of what you can and can't unit-test. You can consider refactoring this method to obtain a Stream from another function (allowing you to mock that function and inject a MemoryStream with test data), but at some point you'll be scraping the edges of your "sandbox" and will just have to trust that the .NET team did their job and that calls to File.Exists, File.Open etc work as expected.
Abstract it away using an interface.
public Interface IFileChecker
{
bool FileExists(string path)
}
Then use the interface to create your mock object.
IFileChecker fileChecker = mocks.Stub<IFileChecker>();
using (mocks.Record())
{
fileChecker.Stub(i => i.FileExists(Arg<string>.Is.Any)).Return(true);
}
Related
I'm looking for some advice on writing some unit tests for the code below. Implementation aside (it's not my code, but I've been tasked to retroactively write some tests for it) could someone suggest how I might test this? I'm not using nUnit or a similar framework; I am using the testing tools built into Visual Studio.
I'm fairly new to writing unit tests, but I imagine I should at least test the following:
Valid response passed into SaveFormBrokerResponse() method
Test for valid exceptions thrown by the catch()
Testing the started Task, but not sure how to do this
I've stripped just a bit out of this function, mostly to do with instantiation and population of some objects:
public void SaveResponse(IForm form, bool isLive, HttpRequestBase request)
{
try
{
var response = new FormBrokerResponses();
// Initialize some vars on response
using (var memory = new MemoryStream())
{
var serializer = new DataContractSerializer(typeof(FormKeyValue[]));
serializer.WriteObject(memory, request.Form.AllKeys.Select(r => new FormKeyValue(r, request.Form[r])).ToArray());
memory.Flush();
memory.Seek(0, SeekOrigin.Begin);
response.Values = Encoding.UTF8.GetString(memory.ToArray());
}
_dataHandler.SaveFormBrokerResponses(response);
}
catch (Exception ex)
{
throw new Exception("boom explosions");
}
Task.Factory.StartNew(() => DispatchFormResponseViaEmail(form, isLive, request.Form.AllKeys.ToDictionary(r => r, r => (object)request.Form[r])));
}
I realize that testing void implementations is tricky and questionable and that there are some integration test concerns here, but that said I can't (currently) change the implementation and need to write tests for what I have.
You can't. You've created a method that fires off an asynchronous operation and then doesn't expose any means of observing the completion/results of that operation to the caller. There are lots of ways of doing this (returning a task, accepting a callback, an event, etc.) but you need to do something for the caller to be able to observe the results of the asynchronous operation. If the method doesn't expose anything, then there is nothing that the caller can reliably do.
If you are allowed to make slight modifications to the code I would do the following which is just a small change anyway :
public void SaveResponse(IForm form, bool isLive, HttpRequestBase request)
{
try
{
var response = new FormBrokerResponses();
// Initialize some vars on response
using (var memory = new MemoryStream())
{
var serializer = new DataContractSerializer(typeof(FormKeyValue[]));
serializer.WriteObject(memory, request.Form.AllKeys.Select(r => new FormKeyValue(r, request.Form[r])).ToArray());
memory.Flush();
memory.Seek(0, SeekOrigin.Begin);
response.Values = Encoding.UTF8.GetString(memory.ToArray());
}
_dataHandler.SaveFormBrokerResponses(response);
}
catch (Exception ex)
{
throw new Exception("boom explosions");
}
Dispatch(form,isLive,request);
}
virtual void Dispatch(IForm form, bool isLive, HttpRequestBase request){
Task.Factory.StartNew(() => DispatchFormResponseViaEmail(form, isLive, request.Form.AllKeys.ToDictionary(r => r, r => (object)request.Form[r])));
}
I don't know what this class is named so suppose the class is named DutClass, you can now derive a different implementation of that class as following:
public class UnitTestClass : DutClass{
override Dispatch(){
//don't do anything or set a state variable that this method was called
}
}
Then instead of testing the DutClass you test the UnitTextClass which has a different implementation of the Dispatch method and does not start a Task at all. You can then test that in fact this method was called, test for the exceptions and so on.
I have been given an old large WinForm application and been asked to write a unit testing project for it.
Asside: The code uses .xlsx files as scripts and these scripts can be complex. My initial (standard practice) idea was to make each test atomic, however, the way the methods that required testing are invoked are complex and dependent on many other code components. So I have decided to invoke a script in order to test the required components...
The code was not written with unit testing in mind and in order to invoke a test I need to first open an .xlsx file; this means my test will have the following structure:
[TestMethod]
public void SomeTest()
{
WorkbookSet workbookSet = Factory.GetWorkbookSet(CultureInfo.CurrentCulture);
Workbook workbook = workbookSet.Workbooks.Add();
workbookSet.GetLock();
try
{
// Open the script.
string testScriptPath = Path.Combine(
Environment.CurrentDirectory, "Scripts\\Test.xlsx");
SSGForm doc = new SSGForm();
if (FileExists(testScriptPath))
OpenExistingWb(ref doc, ref workbookSet, ref workbook, testScriptPath);
// Do testing here...
}
finally
{
workbookSet.ReleaseLock();
}
}
For all test we will have to have the workbookSet/workbook initalisation and Get/ReleaseLock() actions. In my own WPF applications, I have not come accros this problem of code replication before as I have designed the apps to be unit testable from the outset. My question is is there an standard approach in testing of wrapping the actual test code (// Do testing here...) with the boiler plate?
Of course in an actual code I could use a strategy/factory pattern with an interface or merely inject a Func<T, T>(or Action for a void return) into a wrapper method, but is this viable for testing?
Thanks for your time.
Edit. Something like:
private void RunTest(Action action)
{
WorkbookSet workbookSet = Factory.GetWorkbookSet(CultureInfo.CurrentCulture);
Workbook workbook = workbookSet.Workbooks.Add();
workbookSet.GetLock();
try
{
string testScriptPath = Path.Combine(
Environment.CurrentDirectory, "Scripts\\Test.xlsx");
SSGForm doc = new SSGForm();
if (Utils.FileExists(testScriptPath))
mainRibbonForm.OpenExistingWb(ref doc, ref workbookSet, ref workbook, testScriptPath);
// Run the test logic.
action();
}
finally
{
workbookSet.ReleaseLock();
}
}
[TestMethod]
public void SomeTest()
{
RunTest(() =>
{
// Logic here.
});
}
You described the method in your question; to pass the SSGForm to your action, you can just use the Action<T> delegate:
private void RunTest(Action<SSGForm> action)
{
WorkbookSet workbookSet = Factory.GetWorkbookSet(CultureInfo.CurrentCulture);
Workbook workbook = workbookSet.Workbooks.Add();
workbookSet.GetLock();
try
{
string testScriptPath = Path.Combine(
Environment.CurrentDirectory, "Scripts\\Test.xlsx");
SSGForm doc = new SSGForm();
if (Utils.FileExists(testScriptPath))
mainRibbonForm.OpenExistingWb(ref doc, ref workbookSet, ref workbook, testScriptPath);
// Run the test logic.
action(doc);
}
finally
{
workbookSet.ReleaseLock();
}
}
[TestMethod]
public void SomeTest()
{
RunTest(doc =>
{
// Logic here.
Foo(doc);
});
}
I am practicing TDD using MsTest together with RhinoMocks, and I am trying to be as lazy as humanly possible, i.e. make use of VS2012 auto-generation wherever I can. But it doesn't always feel right to create an entire test method with the Arrange-Act-Assert methodology, just to set up my class and its constructors and properties.
Currently, I find it easiest to create some properties in my test class - even if I don't use them - solely for the purpose of code generation. My question is, is this a bad habit, and is there a better/easier way to do it? Any commentary, good or bad is welcome; Thank you!
[TestClass]
public class MainViewModelTest
{
private MainViewModel MainViewModel
{
get
{
var facilityDataEntity = MockRepository.GenerateStub<FacilityDataEntity>();
var viewModel = new MainViewModel(facilityDataEntity)
{
FacilityValue = string.Empty,
FacilityLabel = string.Empty
};
return viewModel;
}
}
private MainViewModel MainViewModelWithFacilityAndShopOrderData
{
get
{
var facilityDataEntity = MockRepository.GenerateStub<FacilityDataEntity>();
var shopOrderDataEntity = MockRepository.GenerateStub<ShopOrderDataEntity>();
var viewModel = new MainViewModel(facilityDataEntity, shopOrderDataEntity)
{
FacilityValue = string.Empty,
FacilityLabel = string.Empty,
ShopOrder = 99999999,
RequiredQuantity = 0M,
ItemCode = string.Empty,
ItemDescription = string.Empty
};
return viewModel;
}
}
[TestMethod]
public void MainViewModel_TranslateDataEntityListMethodReturnsMainViewModelRecords()
{
// Arrange
var facilityDataEntityList = MockRepository.GenerateStub<IEnumerable<FacilityDataEntity>>();
var shopOrderDataEntityList = MockRepository.GenerateStub<IEnumerable<ShopOrderDataEntity>>();
// Act
IEnumerable<MainViewModel> facilityResults = MainViewModel.TranslateDataEntityList(facilityDataEntityList);
IEnumerable<MainViewModel> shopOrderResults = MainViewModel.TranslateDataEntityList(facilityDataEntityList, shopOrderDataEntityList);
// Assert
Assert.IsInstanceOfType(facilityResults, typeof(IEnumerable<MainViewModel>));
Assert.IsInstanceOfType(shopOrderResults, typeof(IEnumerable<MainViewModel>));
}
}
It's not wrong to wrap up common code within your test classes, but I would avoid potentially sharing state between your tests.
There are two approaches you can use here.
Class/Test Initialization
As Peter mentions in his comments, it's easy enough to include initialization methods to do this sort of stuff for you.
//Only runs once per test run
[ClassInitialize]
public void InitClass(){
//Ideally this should be reserved for expensive operations
// or for setting properties that are static throughout
// the lifetime of your test.
}
//Runs for every test
[TestInitialize]
public void TestInit(){
//Here you can setup common stub/mock behavior
// that will be common for every test, but ensure
// it is clean for each test run
}
Setup/Factory Methods
Another option is to create specialized setup or factory methods that can be used to reduce repeated test code and make the intent of your test clearer.
[TestMethod]
public void ShouldFailIfUserNameIsTed(){
var user = SetupUserScenario("Ted");
var result = _myUserService.Validate(user);
Assert.IsFalse(result);
}
private User SetupUserScenario(String username){
var user = new User();
user.Name = username;
//Do a bunch of other necessary setup
return user;
}
Hopefully this all makes sense, but I would also caution you not to go too crazy with this. If you put too much stuff into setup methods, then your tests will be less clear. You should be able to read the test and figure out what is going on without having to inspect a bunch of other places in the code.
That's what the ClassInitialize functionality is for. I would choose expected and recommended means of doing something before anything else. It's more easily recognizable and takes less time to grok the code.
I have a class which uses a StreamWriter to write to a file.
public void CreateLog(string errorLogFilePath, StringBuilder errorLogBuilder, string errorMessage)
{
using (StreamWriter sw = new StreamWriter(errorLogFilePath, true)
{
errorLogBuilder.Apend("An error was discovered.");
//....
sw.Write(errorLogBuilder.ToString());
}
}
[Questions]
1: Is it possible to check that the .Write() method is called?
2: Do i need to wrap a MemoryStream inside the StreamWriter in order to test it, without actually accessing the hard drive. One of StreamWriters constructors accepts a stream but it states the following + will the UTF-8 encoding affect this?
Initializes a new instance of the StreamWriter class for the specified stream by using UTF-8 encoding and the default buffer size.
3: How do you determine if a class is actually accessing the hd and thus needs to be mocked? (sorry if this last question sounds stupid, but im genuinely a little puzzled by this.)
Have the method write to a TextWriter rather than a StreamWriter. Then test the method by passing it a mock TextWriter. In the "real" code, of course, you'll pass in a StreamWriter that was created using new StreamWriter(errorLogFilePath, true).
This yields the following answers to your questions:
Yes
No
You can't generally determine that without decompiling its code.
A little more detail:
Refactor the method into two methods:
public void CreateLog(string errorLogFilePath, StringBuilder errorLogBuilder, string errorMessage)
{
using (StreamWriter sw = new StreamWriter(errorLogFilePath, true)
{
CreateLog(sw, errorLogBuilder, errorMessage);
}
}
public void CreateLog(TextWriter writer, StringBuilder errorLogBuilder, string errorMessage)
{
errorLogBuilder.Apend("An error was discovered.");
//....
writer.Write(errorLogBuilder.ToString());
}
Test the first method to ensure that it calls the second method with an appropriately-constructed StreamWriter. Test the second method to ensure that it calls Write on the passed TextWriter, with appropriate arguments. Now you've abstracted away the dependency on the hard drive. Your tests don't use the hard drive, but you're testing everything.
Generally speaking, you could :
Use a well tested logging library (like NLog, MS Logging Application Block), and spare you developping and maintaining your own.
Refactor your logging logic (or code calling messageboxes, open file dialogs, and so on) into a service, with its interface. This way you can split your testing strategy :
when testing consumers of the loggin service : mock the logging interface to make sure the log method is called. This will ensure that the logging is correctly called by consumers of your logging service
when testing the logging service implementation, just make sure that expected output matches given input : if you want to write "FOO" to bar.log, effectively call
IE :
// arrrange
File.Delete("bar.log")
// act
CreateLog("bar.log", errorLogBuilder, "FOO")
// assert
Assert.IsTrue( File.Exists("bar.log") )
Assert.IsTrue( File.ReadAllLines("bar.log").First() == "FOO")
The point is making sure that the component is called, done by mocking.
Then you can check that the component works as expected.
I know this is a very old question, but I came across this while trying to solve a similar problem.. namely, how to fake the StreamWriter.
The way I went about this was by not having the StreamWriter created inside the method as part of the using statement, but created up front, within the ctor (make your class extend from IDisposable and then destroy the StreamWriter in the Dispose method instead). Then inject a fake over the top of it while under test:
internal class FakeStreamWriter : StreamWriter
{
public List<string> Writes { get; set; } = new List<string>();
public FakeStreamWriter() : base(new MemoryStream()) { }
public override void Write(string value)
{
WriteLine(value);
}
public override void WriteLine(string value)
{
Writes.Add(value);
}
public override void Flush()
{
}
}
My unit test method then looks like this:
public void SmtpStream_Negotiate_EhloResultsCorrectly()
{
var ctx = new APIContext();
var logger = new FakeLogger();
var writer = new FakeStreamWriter();
var reader = new FakeStreamReader { Line = "EHLO test.com" };
var stream = new SmtpStream(logger, ctx, new MemoryStream())
{
_writer = writer,
_reader = reader
};
Exception ex = null;
try
{
stream.Negotiate(ctx);
}
catch (Exception x)
{
ex = x;
}
Assert.IsNull(ex);
Assert.IsTrue(writer.Writes.ElementAt(0) == "250 Hello test.com");
Assert.IsTrue(writer.Writes.ElementAt(1) == "250 STARTTLS");
}
Here's the scenario:
I have a method that reads in a file via a FileStream and a StreamReader in .NET. I would like to unit test this method and somehow remove the dependency on the StreamReader object.
Ideally I would like to be able to supply my own string of test data instead of using a real file. Right now the method makes use of the StreamReader.ReadLine method throughout. What is an approach to modifying the design I have now in order to make this test possible?
Depend on Stream and TextReader instead. Then your unit tests can use MemoryStream and StringReader. (Or load resources from inside your test assembly if necessary.)
Note how ReadLine is originally declared by TextReader, not StreamReader.
The simplest solution would be to have the method accept a Stream as a parameter instead of opening its own FileStream. Your actual code could pass in the FileStream as usual, while your test method could either use a different FileStream for test data, or a MemoryStream filled up with what you wanted to test (that wouldn't require a file).
Off the top of my head, I'd say this is a great opportunity to investigate the merits of Dependency Injection.
You might want to consider redesigning your method so that it takes a delegate that returns the file's contents. One delegate (the production one) might use the classes in System.IO, while the second one (for unit testing), returns the contents directly as a string.
I think the idea is to dependency inject the TextReader and mock it for unit testing. I think you can only mock the TextReader because it is an abstract class.
public class FileParser
{
private readonly TextReader _textReader;
public FileParser(TextReader reader)
{
_textReader = reader;
}
public List<TradeInfo> ProcessFile()
{
var rows = _textReader.ReadLine().Split(new[] { ',' }).Take(4);
return FeedMapper(rows.ToList());
}
private List<TradeInfo> FeedMapper(List<String> rows)
{
var row = rows.Take(4).ToList();
var trades = new List<TradeInfo>();
trades.Add(new TradeInfo { TradeId = row[0], FutureValue = Convert.ToInt32(row[1]), NotionalValue = Convert.ToInt32(row[3]), PresentValue = Convert.ToInt32(row[2]) });
return trades;
}
}
and then Mock using Rhino Mock
public class UnitTest1
{
[Test]
public void Test_Extract_First_Row_Mocked()
{
//Arrange
List<TradeInfo> listExpected = new List<TradeInfo>();
var tradeInfo = new TradeInfo() { TradeId = "0453", FutureValue = 2000000, PresentValue = 3000000, NotionalValue = 400000 };
listExpected.Add(tradeInfo);
var textReader = MockRepository.GenerateMock<TextReader>();
textReader.Expect(tr => tr.ReadLine()).Return("0453, 2000000, 3000000, 400000");
var fileParser = new FileParser(textReader);
var list = fileParser.ProcessFile();
listExpected.ShouldAllBeEquivalentTo(list);
}
}
BUT the question lies in the fact whether it is a good practice to pass such an object from the client code rather I feel it should be managed with using within the class responsible for processing. I agree with the idea of using a sep delegate for the actual code and one for the unit testing but again that is a bit of extra code in production. I may be a bit lost with the idea of dependency injection and mocking to even file IO open/read which actually is not a candidate for unit testing but the file processing logic is which can be tested by just passing the string content of the file (AAA23^YKL890^300000^TTRFGYUBARC).
Any ideas please! Thanks