根据一些业务逻辑,您需要定期向某些用户发送电子邮件(例如,时事通讯)。
以MongoDB为例,当然持久性可以根据您的喜好进行更改。
为您的内部模块和功能制定明确的合作者和职责是很重要的。
如果您通过使用TDD测试驱动应用程序来启动应用程序,这几乎是免费的。
TEST(向尚未收到新闻稿的用户发送新闻稿';,异步t=>;{等待UserRepository.insert({name:';test';,email:';[电子邮件受保护]';,lastEmailSentAt:null})等待新闻稿。run()//我应该在此声明什么?//我们需要新闻稿的协作者.})。
为了定义合作者,我尝试遵循单一责任原则(来自可靠原则家族)。
您可以更进一步,从业务角度来看待它:
谁是与特定软件组件或模块相关联的";角色(如个人或业务部门)?
它断言在调用findNotYetReceivedNewsletter方法时,返回了正确的用户数。
测试(';查找尚未收到时事通讯的用户';,异步t=>;{等待UsersCollection.insert({name:';test';,email:';[电子邮件受保护]';,lastEmailSentAt:New Date()})等待UsersCollection.insert({name:';test';,email:';[电子邮件受保护。)const Users=await userRepository.findNotYetReceivedNewsletter()t.true(Array.isArray(Users))t.is(users.length,1)t.true(UsersCollection.find.calledOnce)t.true(UsersCollection.find.calledWith({lastEmailSentAt:null}))})。
在这种情况下,电子邮件的实际发送是已清除的,因此不会实际发送任何电子邮件。
test(将时事通讯发送给用户';,异步t=>;{const user={name:';test';,email:';[电子邮件受保护]';,lastEmailSentAt:null}const emailStub=sinon.stub(email,';send';)等待emailService.sendTo(User)t.is(emailStub.callCount,
人们可能倾向于将所有逻辑放在一个函数中,然后就到此为止。
它可能会奏效,但能持续多久呢?或者更好的是:如何有效地测试它?
在第一个UAT中,我认为很明显,我们需要提供时事通讯模块,至少提供一种方法来检索用户。
让我们在UserRepository中尝试一下,并断言已查询Users集合以查找尚未收到时事通讯的用户:
test(';向尚未收到的用户发送时事通讯';,异步t=>;{等待db.get(';用户';).insert({name:';test';,email:';[电子邮件受保护]';,lastEmailSentAt:null})sinon.spy(userRepository,';findNotYetReceivedNewsLetter&)。)等待时事通讯。运行(用户存储库)t.is(userRepository.findNotYetReceivedNewsletter.callCount,1)//我们仍需要协作者来发送时事通讯.})。
使用.spy,因为我希望查询数据库,并在稍后断言函数已被调用。
对于电子邮件,我不希望调用真正的函数,因此使用.stub。
我在测试中传入了合作者,并在应用程序代码中使用真正的实现。
异步函数运行(userRepository,emailService){const Users=await userRepository.findNotYetReceivedNewster()for(用户的const用户){await emailService.sendTo(User)}}。
test(';向尚未收到的用户发送时事通讯';,异步t=>;{等待db.get(';用户';).insert({name:';test';,email:';[电子邮件受保护]';,lastEmailSentAt:null})sinon.spy(userRepository,';findNotYetReceivedNewsLetter&)。)等待时事通讯.run(userRepository,emailService)t.is(userRepository.findNotYetReceivedNewsletter.callCount,1)t.is(emailService.sendTo.callCount,1)//实现您关于参数的断言,如电子邮件的";收件人";,";主题";,";内容等})。
├──index.js├──index.test.js├──lib│├──db.js│├──Email-Service.js│├──Email-Service.test.js│├──email.js│├──email.test.js│├──User-Repository.js│└──User-Repository.test.js├──Package.lock.json└──Package.json。
其他软件组件都经过了单元测试,有关更多详细信息,请查看GitHub上的项目
每个合作者都有自己的测试(除了lib/db.js,因为它是一个围绕monk的简单包装器,已经经过了很好的测试)。
js是选择用来发送电子邮件的API的包装器,并且有一个公开的函数.Send。