Closed DeanPhillipsOKC closed 5 years ago
I have interest in this as well. In my private testing suite with Lemur, I already have something to create shims as seen through this test, however LPG has stated he wants to make sure tests that run in Lemur also run in Roblox, thus shimming in the manner of overriding existing behavior is not in the scope of Lemur, is my understanding. This would have to be a separate project. :(
@DeanPhillipsOKC
This concept seems sound to me, but I'm not entirely sure why you need string require! Can you load DataStore2 into your Lemur DataModel
and require it as a ModuleScript
instead? Then you'd get compatibility with real Roblox without needing to reach outside the world to grab a dependency.
@Kampfkarren I think what you suggested is a bit different. What's suggested here is what I think you should be doing as well. Instead of trying to mock the actual services that you're getting via Roblox APIs, you should write small wrappers that you can dependency inject instead.
Instead of trying to mock the actual services that you're getting via Roblox APIs, you should write small wrappers that you can dependency inject instead.
I have an issue in my repository that brings this up and all the benefits I'd get that's mentioned everywhere throughout the code, I just haven't gotten around to it yet 😛
Can you load DataStore2 into your Lemur DataModel and require it as a ModuleScript instead?
Sort of? I had to do weird hacks.
@DeanPhillipsOKC This concept seems sound to me, but I'm not entirely sure why you need string require! Can you load DataStore2 into your Lemur
DataModel
and require it as aModuleScript
instead? Then you'd get compatibility with real Roblox without needing to reach outside the world to grab a dependency.
Good point. I think I originally did it that way because I didn't want the mock files getting pulled into studio (typically on other platforms you don't deploy unit test files), but after considering your question, I realize that I am missing out on some extra verification by doing it this way (e.g., the model.json files are being pulled in correctly by Rojo). I'll take a look when I get out of work.
Thank you both for the replies!
So I feel dumb now. After getting home, and taking a look at my code, it all came back to me. After struggling early on to get absolute paths (e.g. game.ServerScriptService.lib.DataStore2) to work correctly in Lemur, I convinced myself that Lemur could only accommodate unit tests as long as they use relative pathing in their require statements (e.g., script.Dependencies).
Now that I'm comfortable with the stack I'm using (Roact, Rodux, Roji, TestEZ, and Lemur), I decided to take another stab at the Lemur documentation, and realized that early on, I never set to the parent of my test folder to the lemur service hierarchy. once I did that everything works like a charm!
Thanks, for getting me on the right track. Now, I can get rid of the hack, and enjoy better coverage.
I think if I can cook up a DI framework (along the lines of autofac, or ninject), and get rid of all of that dependency module boilerplate, I'll have some pretty decent test tools. I'll also take the branch with "spies" for a spin, as I love Jasmine spies, and mocking frameworks.
Thank you both for the contributions to this amazing framwork, and the others.
Since this was more me not knowing how lemur works, than an actual issue, I went ahead and closed it.
I might be using Lemur, and TestEZ incorrectly, but coming from a C# and Java background where I'm used to unit testing frameworks like NUnit, JUnit, Mockito, and Moq where IoC principles are normally used when developing the units under test, and dependencies are controlled by the instantiator of the class (not the class itself) which makes them easy to mock.
I made a small change to Lemur, that will use the native lua "require" instead of the Lemur habitat implementation, if the parameter is a string. This allows me to load mock implementations from the filesystem, rather than the Lemur habitat.
E.g. Here is a simple "class" that I want to test. Most code has been left out for simplicity, but this module has several dependencies that I don't want to test (e.g., DataStore2)
Instead of explicitly defining dependencies, I use a script called Dependencies.lua that is a child of the PlayerEntity script.
This allows the unit test to override the dependencies with ad hoc tables, or scripts from a mock repository.
This works because of a small change I made to Leumur.
This will allow the main test script to add mock repository locations to the lua require path. It seems like this would be a good feature for everybody to use (especially those of us used to basing the majority of our testing on IoC principles and mainstream testing tools), assuming that it isn't a huge departure from the vision of Lemur.