c# - Unit Testing - How to test long running external processes -
i have method calls method class in turn executes numerous private methods within second class. 1 method writes file picked external process, external process runs between 5 30 mins depending on needs processed, file produced picked application reads , returns data initial method called.
i know described not "unit" method public, question need test in method , how mock call method within second class? or let method run whether 5 mins or 30 mins?
class { public list<dataclass> methodundertest() { list<string> requireddata; secondclass b = new secondclass(); requireddata = b.generatefile(); //b.generatefile() executes number of private methods within secondclass, //this can treated service call. runs between 5 , 30 mins return requireddata.select(r => new dataclass{ property1 = r.substring(0,2), property2 = r.substring(3,5), property3 = r.substring(9,10) }).tolist(); } }
treat secondclass
3rd party dependency , encapsulate behind code control. create abstraction of functionality want dependency;
public interface isecondclass { list<string> generatefile(); }
class has many concerns , should remove responsibilities/concerns not belong class a.
public interface idataclassparser { dataclass parse(string data); } public class defaultdataclassparser : idataclassparser { public dataclass parse(string data) { return new dataclass { property1 = data.substring(0, 2), property2 = data.substring(3, 5), property3 = data.substring(9, 10) }; } }
the above naive example demonstration purposes.
refactor target class explicitly depend on abstraction , not on concretion.
public class { private readonly isecondclass b; private readonly idataclassparser parser; public a(isecondclass b, idataclassparser parser) { this.b = b; this.parser = parser; } public list<dataclass> methodundertest() { list<string> requireddata = b.generatefile(); return requireddata.select(createnewdataclass).tolist(); } private dataclass createnewdataclass(string r) { return parser.parse(r); } }
class a
no longer tightly coupled implementation concerns , method under test can tested in isolation.
example test
[testclass] public class atest { [testmethod] public void methodundertest_should_return_dataclasslist() { //arrange list<string> mockdata = new list<string>(); //todo: populate mockdata var mockb = new mock<isecondclass>(); mockb.setup(_ => _.generatefile()).returns(mockdata); var sut = new a(mockb.object, new defaultdataclassparser()); //act var actual = sut.methodundertest(); //assert //todo: assert actual result satisfies expectations } }
technically above testing parser , additional test can written test parsing code in isolation.
[testclass] public class dataclassparsertest { [testmethod] public void dataclassparser_should_return_dataclass() { //arrange string mockdata = "..."; //todo: populate mockdata var sut = new defaultdataclassparser(); //act var actual = sut.parse(mockdata); //assert //todo: assert actual result satisfies expectations } }
finally, in production, implementation of long running class derive abstraction , encapsulate dependent secondclass
public class secondclasswrapper : isecondclass { private secondclass b = new secondclass(); public list<string> generatefile() { return b.generatefile(); } }
Comments
Post a Comment