英文:
Mock awsEventStream
问题
我有一个如下的函数,我尝试模拟 aws s3 selectobjectcontentoutput,但都没有成功。我甚至尝试了 s3fice,它说:s3iface 包提供了一个接口,用于在测试代码时模拟 Amazon Simple Storage Service 服务客户端。
func awsEventStream(resp *s3.SelectObjectContentOutput) string {
---
return awsResponse
}
我正在尝试编写上述函数的测试用例,如下所示,s3 中有各种方法,但我只需要模拟主类中使用的方法。
package main
import (
"github.com/aws/aws-sdk-go/service/s3"
"testing"
)
type SelectObjectContentOutput struct {
s3.SelectObjectContentOutput
}
func (m *SelectObjectContentOutput) EventStream(input *s3.SelectObjectContentInput) (*s3.SelectObjectContentOutput, error) {
output := &s3.SelectObjectContentOutput{
EventStream: nil,
}
return output, nil
}
func TestAwsEventStream(t *testing.T) {
mockSvc := &SelectObjectContentOutput{}
awsEventStream(&mockSvc.SelectObjectContentOutput)
}
英文:
I have a function as below, I have tried mocking the aws s3 selectobjectcontentoutput but all in vain. I have even tried s3fice which says: Package s3iface provides an interface to enable mocking the Amazon Simple Storage Service service client for testing your code.
func awsEventStream(resp *s3.SelectObjectContentOutput) string {
---
return awsResponse
}
I am trying to write test case for the above as below, there are various methopds in s3 but I eed to mock only the method used in my main class.
package main
import (
"github.com/aws/aws-sdk-go/service/s3"
"testing"
)
type SelectObjectContentOutput struct {
s3.SelectObjectContentOutput
}
func (m *SelectObjectContentOutput) EventStream(input *s3.SelectObjectContentInput) (*s3.SelectObjectContentOutput, error) {
output := &s3.SelectObjectContentOutput{
EventStream: nil,
}
return output, nil
}
func TestAwsEventStream(t *testing.T) {
mockSvc := &SelectObjectContentOutput{}
awsEventStream(&mockSvc.SelectObjectContentOutput)
}
答案1
得分: 4
无法模拟SelectObjectContentOutput。我们得到的EventStream为null。
创建s3.SelectObjectContentOutput
时,需要指定EventStream
属性。从阅读s3 SelectObjectContentEventStream文档中得知:
为了测试和模拟事件流,应该通过NewSelectObjectContentEventStream构造函数来初始化此类型。使用功能选项传递嵌套的模拟行为。
文档还包括如何使用NewSelectObjectContentEventStream
的示例。
es := NewSelectObjectContentEventStream(func(o *SelectObjectContentEventStream){
o.Reader = myMockStreamReader
o.StreamCloser = myMockStreamCloser
})
对于这个问题,我们可以通过将StreamCloser
设置为空的ReadCloser来忽略它。
设置Reader SelectObjectContentEventStreamReader
会更加棘手,因为它是一个接口,从外观上看,s3没有提供直接构造读取器的方法。不过我们可以创建一个实现它的类型:
type stubSelectObjectContentEventStreamReader struct {
StreamEvents <-chan s3.SelectObjectContentEventStreamEvent
Error error
}
func (s stubSelectObjectContentEventStreamReader) Events() <-chan s3.SelectObjectContentEventStreamEvent {
return s.StreamEvents
}
func (s stubSelectObjectContentEventStreamReader) Close() error {
return nil
}
func (s stubSelectObjectContentEventStreamReader) Err() error {
return s.Error
}
将它们整合在一起:
func TestAwsEventStream(t *testing.T) {
streamEvents := make(chan s3.SelectObjectContentEventStreamEvent, 3)
eventStreamReader := stubSelectObjectContentEventStreamReader{
StreamEvents: streamEvents,
Error: nil,
}
mockEventStream := s3.NewSelectObjectContentEventStream(func(o *s3.SelectObjectContentEventStream) {
o.Reader = eventStreamReader
o.StreamCloser = io.NopCloser(bytes.NewReader(nil))
})
mockOutput := &s3.SelectObjectContentOutput{
EventStream: mockEventStream,
}
streamEvents <- &s3.RecordsEvent{Payload: []byte("hello world")}
streamEvents <- &s3.EndEvent{}
close(streamEvents)
got := awsEventStream(mockOutput)
want := "hello world"
if got != want {
t.Errorf("got %v, want %v", got, want)
}
}
英文:
> Not able to mock SelectObjectContentOutput. We are getting the EventStream as null.
When creating s3.SelectObjectContentOutput
, you need to specify the EventStream
attribute. From reading the s3 SelectObjectContentEventStream docs:
> For testing and mocking the event stream this type should be initialized via the NewSelectObjectContentEventStream constructor function. Using the functional options to pass in nested mock behavior.
The docs also include example on how to use NewSelectObjectContentEventStream
.
es := NewSelectObjectContentEventStream(func(o *SelectObjectContentEventStream){
o.Reader = myMockStreamReader
o.StreamCloser = myMockStreamCloser
})
For this question, we can ignore StreamCloser
by setting it to empty ReadCloser.
Setting the Reader SelectObjectContentEventStreamReader
will be trickier because it is an interface and from the look of it, s3 does not provide a direct way to construct the reader. Thought we can just create a type that implements it:
type stubSelectObjectContentEventStreamReader struct {
StreamEvents <-chan s3.SelectObjectContentEventStreamEvent
Error error
}
func (s stubSelectObjectContentEventStreamReader) Events() <-chan s3.SelectObjectContentEventStreamEvent {
return s.StreamEvents
}
func (s stubSelectObjectContentEventStreamReader) Close() error {
return nil
}
func (s stubSelectObjectContentEventStreamReader) Err() error {
return s.Error
}
Putting it all together:
func TestAwsEventStream(t *testing.T) {
streamEvents := make(chan s3.SelectObjectContentEventStreamEvent, 3)
eventStreamReader := stubSelectObjectContentEventStreamReader{
StreamEvents: streamEvents,
Error: nil,
}
mockEventStream := s3.NewSelectObjectContentEventStream(func(o *s3.SelectObjectContentEventStream) {
o.Reader = eventStreamReader
o.StreamCloser = io.NopCloser(bytes.NewReader(nil))
})
mockOutput := &s3.SelectObjectContentOutput{
EventStream: mockEventStream,
}
streamEvents <- &s3.RecordsEvent{Payload: []byte("hello world")}
streamEvents <- &s3.EndEvent{}
close(streamEvents)
got := awsEventStream(mockOutput)
want := "hello world"
if got != want {
t.Errorf("got %v, want %v", got, want)
}
}
答案2
得分: 2
@wijayaerick给出的答案是正确的,应该涵盖了大约60%的代码。但是,如果OP想要覆盖100%的测试用例,那么他需要遍历所有的switch case语句。以下是我尝试过的代码,它按需工作。
你需要更改的几个地方是:
将通道大小更改为3 streamEvents := make(chan s3.SelectObjectContentEventStreamEvent, 3)
将RecordsEvent
、EndEvent
和StatsEvent
添加到streamEvents
中,如下所示:
statsEvent := &s3.StatsEvent{
Details: &s3.Stats{
BytesScanned: aws.Int64(1024),
BytesProcessed: aws.Int64(2048),
},
}
streamEvents <- &s3.RecordsEvent{Payload: []byte("hello world")}
streamEvents <- &s3.EndEvent{}
streamEvents <- statsEvent
你的整体代码将如下所示:
package main
import (
"bytes"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/s3"
"io"
"testing"
)
type stubSelectObjectContentEventStreamReader struct {
StreamEvents <-chan s3.SelectObjectContentEventStreamEvent
Error error
}
func (s stubSelectObjectContentEventStreamReader) Events() <-chan s3.SelectObjectContentEventStreamEvent {
return s.StreamEvents
}
func (s stubSelectObjectContentEventStreamReader) Close() error {
return nil
}
func (s stubSelectObjectContentEventStreamReader) Err() error {
return s.Error
}
func TestAwsEventStream(t *testing.T) {
type testCase struct {
arg1 s3.SelectObjectContentEventStreamEvent
want s3.SelectObjectContentEventStreamEvent
}
streamEvents := make(chan s3.SelectObjectContentEventStreamEvent, 3)
eventStreamReader := stubSelectObjectContentEventStreamReader{
StreamEvents: streamEvents,
Error: nil,
}
mockEventStream := s3.NewSelectObjectContentEventStream(func(o *s3.SelectObjectContentEventStream) {
o.Reader = eventStreamReader
o.StreamCloser = io.NopCloser(bytes.NewReader(nil))
})
mockOutput := &s3.SelectObjectContentOutput{
EventStream: mockEventStream,
}
statsEvent := &s3.StatsEvent{
Details: &s3.Stats{
BytesScanned: aws.Int64(1024),
BytesProcessed: aws.Int64(2048),
},
}
streamEvents <- &s3.RecordsEvent{Payload: []byte("hello world")}
streamEvents <- &s3.EndEvent{}
streamEvents <- statsEvent
close(streamEvents)
got := awsEventStream(mockOutput)
want := "hello world"
if got != want {
t.Errorf("got %v, want %v", got, want)
}
}
英文:
The answer given by @wijayaerick is appropriate and should cover around 60% of the code. But in case OP wants to cover the test case to 100% then he needs to traverse all the switch case statements. Below is my code that I have tried and it works as needed.
Few things that you would need to change is:
Make channel size to 3 streamEvents := make(chan s3.SelectObjectContentEventStreamEvent, 3)
Add RecordsEvent
, EndEvent
and StatsEvent
to streamEvents
as below:
statsEvent := &s3.StatsEvent{
Details: &s3.Stats{
BytesScanned: aws.Int64(1024),
BytesProcessed: aws.Int64(2048),
},
}
streamEvents <- &s3.RecordsEvent{Payload: []byte("hello world")}
streamEvents <- &s3.EndEvent{}
streamEvents <- statsEvent
Your overall code will look like below:
package main
import (
"bytes"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/s3"
"io"
"testing"
)
type stubSelectObjectContentEventStreamReader struct {
StreamEvents <-chan s3.SelectObjectContentEventStreamEvent
Error error
}
func (s stubSelectObjectContentEventStreamReader) Events() <-chan s3.SelectObjectContentEventStreamEvent {
return s.StreamEvents
}
func (s stubSelectObjectContentEventStreamReader) Close() error {
return nil
}
func (s stubSelectObjectContentEventStreamReader) Err() error {
return s.Error
}
func TestAwsEventStream(t *testing.T) {
type testCase struct {
arg1 s3.SelectObjectContentEventStreamEvent
want s3.SelectObjectContentEventStreamEvent
}
streamEvents := make(chan s3.SelectObjectContentEventStreamEvent, 3)
eventStreamReader := stubSelectObjectContentEventStreamReader{
StreamEvents: streamEvents,
Error: nil,
}
mockEventStream := s3.NewSelectObjectContentEventStream(func(o *s3.SelectObjectContentEventStream) {
o.Reader = eventStreamReader
o.StreamCloser = io.NopCloser(bytes.NewReader(nil))
})
mockOutput := &s3.SelectObjectContentOutput{
EventStream: mockEventStream,
}
statsEvent := &s3.StatsEvent{
Details: &s3.Stats{
BytesScanned: aws.Int64(1024),
BytesProcessed: aws.Int64(2048),
},
}
streamEvents <- &s3.RecordsEvent{Payload: []byte("hello world")}
streamEvents <- &s3.EndEvent{}
streamEvents <- statsEvent
close(streamEvents)
got := awsEventStream(mockOutput)
want := "hello world"
if got != want {
t.Errorf("got %v, want %v", got, want)
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论