How to harness "File.Open"? What are good strategies?

4 posts, 1 answers
  1. Tormod
    Tormod avatar
    38 posts
    Member since:
    Jul 2012

    Posted 16 Aug 2010 Link to this post

    Hi.

    My test projects have data files as part of the solution. To avoid dependencies on the file system on the CI server, I embed them in the test assembly as manifest resources. The problem is when I intercept File.Open calls using JustMock. What do I do? What do I return? Do I pass it a Mock<FileInfo>? Since "File.Open()" is mentioned about as often as "DateTime.Now" to show the strengths of TypeMock and JustMock, what are good practices/strategies to employ when dealing with it?

    http://stackoverflow.com/questions/3466355/how-can-i-pass-a-solution-resource-as-a-filestream-object-to-an-intercepted-file
  2. Answer
    Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 16 Aug 2010 Link to this post

    Hi  Tormod,
    I prepared a sample based on your requirement and added that to the stackoverlow question that you have asked.

    Just to let you know that  I found a issue with Arg.IsAny<byte[]> and the example is done with a fixed  internal version. If you are interested I can provide you the build  to the email you have specified in your Telerik account along with the Mock.Partial(..).ForAll fix  for the other System.Environment related issue.

    Regards,
    Mehfuz


    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  3. DevCraft R3 2016 release webinar banner
  4. Tormod
    Tormod avatar
    38 posts
    Member since:
    Jul 2012

    Posted 17 Aug 2010 Link to this post

    Thanks a lot! This was definitely useful.
    There was a trick there that I didn't expect. I guess I need to tune in to the power of JustMock.

    After creating this object like this:
    FileStream fs = (FileStream)FormatterServices.GetSafeUninitializedObject(typeof(FileStream));  

    I had to read this line at least three times.
    Mock.Arrange(() => fs.Write(Arg.IsAny<byte[]>(), Arg.AnyInt, Arg.AnyInt)

    Can you take any single method on any running instance of any type and just mock it?
    My thought was that I would create a <FileInfo> mock. And return it from statically mocked File.Open().

    I still need to work out how to be able to create a FileInfo object which in actuality reads from a test project resource, but this helped me a long way. And I can fiddle around with it myself.
    I don't have an immediate need for it, but I hope you get the argument Arg.Any<> clause object figured out.

    For clarity and posterity in this thread I've included your solution. 

            byte[] actual = new byte[255]; 
     
           
    // writing locally, can be done from resource manifest as well. 
     
           
    using (StreamWriter writer = new StreamWriter(new MemoryStream(actual))) 
           
    { 
                writer
    .WriteLine("Hello world"); 
                writer
    .Flush(); 
           
    } 
     
           
    // arrange the file system. 
     
           
    FileStream fs = (FileStream)FormatterServices.GetSafeUninitializedObject(typeof(FileStream)); 
     
           
    // mocking the specific call and setting up expectations. 
           
    Mock.Arrange(() => fs.Write(Arg.IsAny<byte[]>(), Arg.AnyInt, Arg.AnyInt)) 
               
    .DoInstead((byte[] content, int offset, int len) => 
           
    { 
                actual
    .CopyTo(content, offset); 
           
    }); 
     
           
    // return custom filestream for File.Open. 
           
    Mock.Arrange(() => File.Open(Arg.AnyString, Arg.IsAny<FileMode>())).Returns(fs); 
     
     
           
    // act 
           
    var fileStream =  File.Open("hello.txt", FileMode.Open); 
           
    byte[] fakeContent = new byte[actual.Length]; 
     
           
    // original task 
            fileStream
    .Write(fakeContent, 0, actual.Length); 
     
           
    // assert 
           
    Assert.Equal(fakeContent.Length, actual.Length); 
     
           
    for (var i = 0; i < fakeContent.Length; i++) 
           
    { 
               
    Assert.Equal(fakeContent[i], actual[i]); 
           
    } 
  5. Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 17 Aug 2010 Link to this post

    Hello Tormod,

    It's nice that things helped you a bit. About the Arg.IsAny<T>(), it is also possible to write it in the following way to ignore any arguments specified:


    Mock.Arrange(() => fs.Write(null, 0, 0).IgnoreArgument();

    Secondly, it is also possible to create the instance of FileStream using Mock.Create<T>() but since here we are using specifically fs.Write method, other ways like creating  the instance using FormatterServices can significantly reduce the test execution time.



    Hope that helps,
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
Back to Top