무엇을 해야 합니까?
MessageService 생성 및 테스트 코드 작성
참조
메시지 모델
/모델/message_model.dart
- from : 메시지를 보낸 사용자의 ID
- to: 메시지를 받는 사용자의 ID
import 'package:flutter/foundation.dart';
class Message {
String get id => _id;
String _id;
/// from : sender id
/// to : receiver id
final String from;
final String to;
final DateTime timestamp;
final String contents;
Message(
{@required this.from,
@required this.to,
@required this.timestamp,
@required this.contents});
toJson() =>
{'from': from, 'to': to, 'timestamp': timestamp, 'contents': contents};
factory Message.fromJson(Map<String, dynamic> json) {
var message = Message(
from: json('from'),
to: json('to'),
timestamp: json('timestamp'),
contents: json('contents'));
message._id = json('id');
return message;
}
}
메시지 서비스
/서비스/message_service_impl.dart
- 메시징 서비스에서 구현해야 하는 메소드는 send, messages 및 dispose입니다.
- 보내기: 메시지 보내기
- 메시지: 특정 사용자로부터 받은 메시지를 반환합니다.
- 버리다 : 화합물을 버리다
import 'package:flutter/cupertino.dart';
import 'package:flutter_prj/model/message_model.dart';
import '../model/user_model.dart';
abstract class IMessageService {
Future<bool> send(Message message);
Stream<Message> messages({@required User user});
dispose();
}
/서비스/user_service.dart
import 'dart:async';
import 'package:flutter_prj/model/message_model.dart';
import 'package:flutter_prj/model/user_model.dart';
import 'package:flutter_prj/service/message_service_impl.dart';
import 'package:logger/logger.dart';
import 'package:rethinkdb_dart/rethinkdb_dart.dart';
class MessageService implements IMessageService {
final Connection _connection;
final Rethinkdb _db;
// 에러 발생시 로깅
var _logger = Logger();
final _controller = StreamController<Message>.broadcast();
StreamSubscription _changefeed;
MessageService(this._db, this._connection);
@override
dispose() {
// 구독 취소
_changefeed?.cancel();
_controller?.close();
}
@override
Stream<Message> messages({User user}) {
_startReceivingMessages(user);
return _controller.stream;
}
@override
Future<bool> send(Message message) async {
// Message를 받아서 데이터베이스에 저장
Map record =
await _db.table('messages').insert(message.toJson()).run(_connection);
// DB에 데이터가 잘 들어갔는지 여부를 반환
return record('inserted') == 1;
}
_startReceivingMessages(User user) {
_changefeed = _db
.table('messages')
.filter({'to': user.id})
.changes({'include_initial': true})
.run(_connection)
.asStream()
.cast<Feed>()
.listen((event) {
event
.forEach((feedData) {
if (feedData('new_val') == null) return;
final message = _messageFromFeed(feedData);
_controller.sink.add(message);
_removeDeliveredMessage(message);
})
.catchError((err) => _logger.e(err))
.onError((err, stackTrace) => _logger.e(err));
});
}
Message _messageFromFeed(feedData) {
return Message.fromJson(feedData('new_val'));
}
_removeDeliveredMessage(Message message) {
_db
.table('messages')
.get(message.id)
.delete({'return_changes': false}).run(_connection);
}
}
테스트 코드
테스트/util_for_test.dart
- 테스트 시작시 △ test라는 데이터베이스 생성 △ 사용자 테이블 생성 메시지 테이블 생성
- 시험이 끝날 때 △ 사용자 테이블 삭제 메시지 테이블 지우기
import 'package:rethinkdb_dart/rethinkdb_dart.dart';
Future<void> createDatabase(Rethinkdb db, Connection connection) async {
await db.dbCreate('test').run(connection).catchError((err) => {});
await db.tableCreate('users').run(connection).catchError((err) => {});
await db.tableCreate('messages').run(connection).catchError((err) => {});
}
Future<void> cleanDatabase(Rethinkdb db, Connection connection) async {
await db.table('users').delete().run(connection);
await db.table('messages').delete().run(connection);
}
테스트/message_service_test.dart
import 'package:flutter_prj/model/message_model.dart';
import 'package:flutter_prj/model/user_model.dart';
import 'package:flutter_prj/service/message_service.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:rethinkdb_dart/rethinkdb_dart.dart';
import 'util_for_test.dart';
void main() {
Rethinkdb _db = Rethinkdb();
Connection _connection;
MessageService sut;
setUp(() async {
_connection = await _db.connect(host: '127.0.0.1', port: 28015);
await createDatabase(_db, _connection);
sut = MessageService(_db, _connection);
});
tearDown(() async {
sut.dispose();
await cleanDatabase(_db, _connection);
});
final sender =
User.fromJson({'id': '1', 'active': true, 'lastSeen': DateTime.now()});
final receiver =
User.fromJson({'id': '2', 'active': true, 'lastSeen': DateTime.now()});
test('if message sent successfully, then return true', () async {
Message message = Message(
from: sender.id,
to: receiver.id,
timestamp: DateTime.now(),
contents: 'test message');
final result = await sut.send(message);
expect(result, true);
});
test('sending message works successfully', () async {
sut.messages(user: receiver).listen(expectAsync1((message) {
expect(message.to, receiver.id);
expect(message.id, isNotEmpty);
}, count: 2));
Message firstMessage = Message(
from: sender.id,
to: receiver.id,
timestamp: DateTime.now(),
contents: 'test message');
Message secondMessage = Message(
from: sender.id,
to: receiver.id,
timestamp: DateTime.now(),
contents: 'test message');
await sut.send(firstMessage);
await sut.send(secondMessage);
});
test('successfully subscribe and receive messages', () async {
sut.messages(user: receiver).listen(expectAsync1((message) {
expect(message.to, receiver.id);
expect(message.id, isNotEmpty);
}, count: 2));
Message message = Message(
from: sender.id,
to: receiver.id,
timestamp: DateTime.now(),
contents: 'this is a message',
);
Message secondMessage = Message(
from: sender.id,
to: receiver.id,
timestamp: DateTime.now(),
contents: 'this is another message',
);
await sut.send(message);
await sut.send(secondMessage);
});
test('successfully subscribe and receive new messages ', () async {
Message message = Message(
from: sender.id,
to: receiver.id,
timestamp: DateTime.now(),
contents: 'this is a message',
);
Message secondMessage = Message(
from: sender.id,
to: receiver.id,
timestamp: DateTime.now(),
contents: 'this is another message',
);
await sut.send(message);
await sut.send(secondMessage).whenComplete(
() => sut.messages(user: receiver).listen(
expectAsync1((message) {
expect(message.to, receiver.id);
}, count: 2),
),
);
});
}
테스트 실행
Docker 컨테이너 실행
docker run -d -p 8080:8080 -p 20815:20815 rethinkdb
테스트 코드 실행


